zxcvbn-ruby 0.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,7 +10,7 @@ describe Zxcvbn::Math do
10
10
  describe '#bruteforce_cardinality' do
11
11
  context 'when empty password' do
12
12
  it 'should return 0 if empty password' do
13
- bruteforce_cardinality('').should eql 0
13
+ expect(bruteforce_cardinality('')).to eql 0
14
14
  end
15
15
  end
16
16
 
@@ -18,7 +18,7 @@ describe Zxcvbn::Math do
18
18
  context 'and a digit' do
19
19
  it 'should return 10' do
20
20
  (0..9).each do |digit|
21
- bruteforce_cardinality(digit.to_s).should eql 10
21
+ expect(bruteforce_cardinality(digit.to_s)).to eql 10
22
22
  end
23
23
  end
24
24
  end
@@ -26,7 +26,7 @@ describe Zxcvbn::Math do
26
26
  context 'and an upper case character' do
27
27
  it 'should return 26' do
28
28
  ('A'..'Z').each do |character|
29
- bruteforce_cardinality(character).should eql 26
29
+ expect(bruteforce_cardinality(character)).to eql 26
30
30
  end
31
31
  end
32
32
  end
@@ -34,7 +34,7 @@ describe Zxcvbn::Math do
34
34
  context 'and a lower case character' do
35
35
  it 'should return 26' do
36
36
  ('a'..'z').each do |character|
37
- bruteforce_cardinality(character).should eql 26
37
+ expect(bruteforce_cardinality(character)).to eql 26
38
38
  end
39
39
  end
40
40
  end
@@ -42,7 +42,7 @@ describe Zxcvbn::Math do
42
42
  context 'and a symbol' do
43
43
  it 'should return 33' do
44
44
  %w|/ [ ` {|.each do |symbol|
45
- bruteforce_cardinality(symbol).should eql 33
45
+ expect(bruteforce_cardinality(symbol)).to eql 33
46
46
  end
47
47
  end
48
48
  end
@@ -51,31 +51,31 @@ describe Zxcvbn::Math do
51
51
  context 'when password is more than one character long' do
52
52
  context 'and only digits' do
53
53
  it 'should return 10' do
54
- bruteforce_cardinality('123456789').should eql 10
54
+ expect(bruteforce_cardinality('123456789')).to eql 10
55
55
  end
56
56
  end
57
57
 
58
58
  context 'and only lowercase characters' do
59
59
  it 'should return 26' do
60
- bruteforce_cardinality('password').should eql 26
60
+ expect(bruteforce_cardinality('password')).to eql 26
61
61
  end
62
62
  end
63
63
 
64
64
  context 'and only uppercase characters' do
65
65
  it 'should return 26' do
66
- bruteforce_cardinality('PASSWORD').should eql 26
66
+ expect(bruteforce_cardinality('PASSWORD')).to eql 26
67
67
  end
68
68
  end
69
69
 
70
70
  context 'and only symbols' do
71
71
  it 'should return 33' do
72
- bruteforce_cardinality('/ [ ` {').should eql 33
72
+ expect(bruteforce_cardinality('/ [ ` {')).to eql 33
73
73
  end
74
74
  end
75
75
 
76
76
  context 'and a mixed of character types' do
77
77
  it 'should add up every character type cardinality' do
78
- bruteforce_cardinality('p1SsWorD!').should eql 95
78
+ expect(bruteforce_cardinality('p1SsWorD!')).to eql 95
79
79
  end
80
80
  end
81
81
  end
@@ -84,25 +84,25 @@ describe Zxcvbn::Math do
84
84
  describe '#average_degree_for_graph' do
85
85
  context 'when keyboard is qwerty' do
86
86
  it 'returns the correct average degree over all keys' do
87
- average_degree_for_graph('qwerty').should eql 4.595744680851064
87
+ expect(average_degree_for_graph('qwerty')).to eql 4.595744680851064
88
88
  end
89
89
  end
90
90
 
91
91
  context 'when keyboard is dvorak' do
92
92
  it 'returns the correct average degree over all keys' do
93
- average_degree_for_graph('dvorak').should eql 4.595744680851064
93
+ expect(average_degree_for_graph('dvorak')).to eql 4.595744680851064
94
94
  end
95
95
  end
96
96
 
97
97
  context 'when keyboard is keypad' do
98
98
  it 'returns the correct average degree over all keys' do
99
- average_degree_for_graph('keypad').should eql 5.066666666666666
99
+ expect(average_degree_for_graph('keypad')).to eql 5.066666666666666
100
100
  end
101
101
  end
102
102
 
103
103
  context 'when keyboard is mac keypad' do
104
104
  it 'returns the correct average degree over all keys' do
105
- average_degree_for_graph('mac_keypad').should eql 5.25
105
+ expect(average_degree_for_graph('mac_keypad')).to eql 5.25
106
106
  end
107
107
  end
108
108
  end
@@ -110,25 +110,25 @@ describe Zxcvbn::Math do
110
110
  describe '#starting_positions_for_graph' do
111
111
  context 'when keyboard is qwerty' do
112
112
  it 'returns the correct average degree over all keys' do
113
- starting_positions_for_graph('qwerty').should eql 94
113
+ expect(starting_positions_for_graph('qwerty')).to eql 94
114
114
  end
115
115
  end
116
116
 
117
117
  context 'when keyboard is dvorak' do
118
118
  it 'returns the correct average degree over all keys' do
119
- starting_positions_for_graph('dvorak').should eql 94
119
+ expect(starting_positions_for_graph('dvorak')).to eql 94
120
120
  end
121
121
  end
122
122
 
123
123
  context 'when keyboard is keypad' do
124
124
  it 'returns the correct average degree over all keys' do
125
- starting_positions_for_graph('keypad').should eql 15
125
+ expect(starting_positions_for_graph('keypad')).to eql 15
126
126
  end
127
127
  end
128
128
 
129
129
  context 'when keyboard is mac keypad' do
130
130
  it 'returns the correct average degree over all keys' do
131
- starting_positions_for_graph('mac_keypad').should eql 16
131
+ expect(starting_positions_for_graph('mac_keypad')).to eql 16
132
132
  end
133
133
  end
134
134
  end
@@ -1,4 +1,4 @@
1
- require 'v8'
1
+ require 'mini_racer'
2
2
  require 'json'
3
3
 
4
4
  module JsHelpers
@@ -6,9 +6,8 @@ module JsHelpers
6
6
  JS_SOURCE_PATH = Pathname(File.expand_path('../js_source/', __FILE__))
7
7
 
8
8
  def initialize
9
- @ctx = V8::Context.new do |ctx|
10
- ctx.eval(JS_SOURCE_PATH.join('compiled.js').read)
11
- end
9
+ @ctx = MiniRacer::Context.new
10
+ @ctx.eval(JS_SOURCE_PATH.join('compiled.js').read)
12
11
  end
13
12
 
14
13
  def eval(string)
@@ -17,7 +17,7 @@ RSpec::Matchers.define :match_js_results do |expected_js_results|
17
17
  @missing.empty? && @extra.empty?
18
18
  end
19
19
 
20
- failure_message_for_should do |actual|
20
+ failure_message do |actual|
21
21
  "Matches missing from ruby results:\n#{@missing.inspect}\nMatches unique to ruby results:\n#{@extra.inspect}"
22
22
  end
23
23
 
@@ -1,4 +1,7 @@
1
- require 'spec_helper'
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ require "spec_helper"
2
5
 
3
6
  describe Zxcvbn::Tester do
4
7
  let(:tester) { Zxcvbn::Tester.new }
@@ -8,44 +11,89 @@ describe Zxcvbn::Tester do
8
11
  ruby_result = tester.test(password)
9
12
  js_result = js_zxcvbn(password)
10
13
 
11
- ruby_result.calc_time.should_not be_nil
12
- ruby_result.password.should eq js_result['password']
13
- ruby_result.entropy.should eq js_result['entropy']
14
- ruby_result.crack_time.should eq js_result['crack_time']
15
- ruby_result.crack_time_display.should eq js_result['crack_time_display']
16
- ruby_result.score.should eq js_result['score']
17
- ruby_result.pattern.should eq js_result['pattern']
18
- ruby_result.match_sequence.count.should eq js_result['match_sequence'].count
14
+ expect(ruby_result.calc_time).not_to be_nil
15
+ expect(ruby_result.password).to eq js_result["password"]
16
+ expect(ruby_result.entropy).to eq js_result["entropy"]
17
+ expect(ruby_result.crack_time).to eq js_result["crack_time"]
18
+ expect(ruby_result.crack_time_display).to eq js_result["crack_time_display"]
19
+ expect(ruby_result.score).to eq js_result["score"]
20
+ expect(ruby_result.pattern).to eq js_result["pattern"]
21
+ expect(ruby_result.match_sequence.count).to eq js_result["match_sequence"].count
22
+
23
+ # NOTE: feedback didn't exist in the version of the JS library this gem
24
+ # is based on, so instead we just check that it put `Feedback` in
25
+ # there. Real tests for its values go in `feedback_giver_spec.rb`.
26
+ expect(ruby_result.feedback).to be_a Zxcvbn::Feedback
19
27
  end
20
28
  end
21
29
 
22
- context 'with a custom user dictionary' do
23
- it 'scores them against the user dictionary' do
24
- result = tester.test('themeforest', ['themeforest'])
25
- result.entropy.should eq 0
26
- result.score.should eq 0
30
+ context "with a custom user dictionary" do
31
+ it "scores them against the user dictionary" do
32
+ result = tester.test("themeforest", ["themeforest"])
33
+ expect(result.entropy).to eq 0
34
+ expect(result.score).to eq 0
27
35
  end
28
36
 
29
- it 'matches l33t substitutions on this dictionary' do
30
- result = tester.test('th3m3for3st', ['themeforest'])
31
- result.entropy.should eq 1
32
- result.score.should eq 0
37
+ it "matches l33t substitutions on this dictionary" do
38
+ result = tester.test("th3m3for3st", ["themeforest"])
39
+ expect(result.entropy).to eq 1
40
+ expect(result.score).to eq 0
41
+ end
42
+ end
43
+
44
+ context "with Unicode entries in the password" do
45
+ it "validates the password" do
46
+ result = tester.test("✅🐴🔋staple", %w[Theme Forest themeforest])
47
+ expect(result.entropy).to be_positive
48
+ expect(result.score).to be_positive
33
49
  end
34
50
  end
35
51
 
36
- context 'with a custom global dictionary' do
37
- before { tester.add_word_lists('envato' => ['envato']) }
52
+ context "with Unicode entries in the dictionary" do
53
+ it "validates the password" do
54
+ result = tester.test("correct horse battery staple", %w[✅ 🐴 🔋])
55
+ expect(result.entropy).to be_positive
56
+ expect(result.score).to be_positive
57
+ end
58
+ end
59
+
60
+ context "with Unicode entries in the password and the dictionary" do
61
+ it "validates the password" do
62
+ result = tester.test("✅🐴🔋staple", %w[✅ 🐴 🔋])
63
+ expect(result.entropy).to be_positive
64
+ expect(result.score).to be_zero
65
+ end
66
+ end
67
+
68
+ context "with invalid entries in the dictionary" do
69
+ it "ignores those entries" do
70
+ result = tester.test("themeforest", [nil, 1, "themeforest"])
71
+ expect(result.entropy).to eq 0
72
+ expect(result.score).to eq 0
73
+ end
74
+ end
75
+
76
+ context "with a custom global dictionary" do
77
+ before { tester.add_word_lists("envato" => ["envato"]) }
78
+
79
+ it "scores them against the dictionary" do
80
+ result = tester.test("envato")
81
+ expect(result.entropy).to eq 0
82
+ expect(result.score).to eq 0
83
+ end
84
+
85
+ context "with invalid entries in a custom dictionary" do
86
+ before { tester.add_word_lists("themeforest" => [nil, 1, "themeforest"]) }
38
87
 
39
- it 'scores them against the dictionary' do
40
- result = tester.test('envato')
41
- result.entropy.should eq 0
42
- result.score.should eq 0
88
+ it "ignores those entries" do
89
+ expect(tester.test("themeforest")).to have_attributes(entropy: 0, score: 0, crack_time: 0)
90
+ end
43
91
  end
44
92
  end
45
93
 
46
- context 'nil password' do
94
+ context "nil password" do
47
95
  specify do
48
- expect { tester.test(nil) }.to_not raise_error
96
+ expect(tester.test(nil)).to have_attributes(entropy: 0, score: 0, crack_time: 0)
49
97
  end
50
98
  end
51
- end
99
+ end
@@ -1,6 +1,8 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  require File.expand_path('../lib/zxcvbn/version', __FILE__)
3
3
 
4
+ GITHUB_URL = 'https://github.com/envato/zxcvbn-ruby'
5
+
4
6
  Gem::Specification.new do |gem|
5
7
  gem.authors = ["Steve Hodgkiss", "Matthieu Aussaguel"]
6
8
  gem.email = ["steve@hodgkiss.me", "matthieu.aussaguel@gmail.com"]
@@ -14,7 +16,18 @@ Gem::Specification.new do |gem|
14
16
  gem.name = "zxcvbn-ruby"
15
17
  gem.require_paths = ["lib"]
16
18
  gem.version = Zxcvbn::VERSION
19
+ gem.license = 'MIT'
20
+
21
+ gem.required_ruby_version = '>= 2.5'
17
22
 
18
- gem.add_development_dependency 'therubyracer'
23
+ gem.add_development_dependency 'mini_racer'
19
24
  gem.add_development_dependency 'rspec'
25
+
26
+ gem.metadata = {
27
+ 'bug_tracker_uri' => "#{GITHUB_URL}/issues",
28
+ 'changelog_uri' => "#{GITHUB_URL}/blob/HEAD/CHANGELOG.md",
29
+ 'documentation_uri' => "#{GITHUB_URL}/blob/HEAD/README.md",
30
+ 'homepage_uri' => GITHUB_URL,
31
+ 'source_code_uri' => GITHUB_URL
32
+ }
20
33
  end
metadata CHANGED
@@ -1,47 +1,42 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zxcvbn-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
5
- prerelease:
4
+ version: 1.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Steve Hodgkiss
9
8
  - Matthieu Aussaguel
10
- autorequire:
9
+ autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2015-04-28 00:00:00.000000000 Z
12
+ date: 2021-01-05 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
- name: therubyracer
15
+ name: mini_racer
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
- - - ! '>='
18
+ - - ">="
21
19
  - !ruby/object:Gem::Version
22
20
  version: '0'
23
21
  type: :development
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
- - - ! '>='
25
+ - - ">="
29
26
  - !ruby/object:Gem::Version
30
27
  version: '0'
31
28
  - !ruby/object:Gem::Dependency
32
29
  name: rspec
33
30
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
  requirements:
36
- - - ! '>='
32
+ - - ">="
37
33
  - !ruby/object:Gem::Version
38
34
  version: '0'
39
35
  type: :development
40
36
  prerelease: false
41
37
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
  requirements:
44
- - - ! '>='
39
+ - - ">="
45
40
  - !ruby/object:Gem::Version
46
41
  version: '0'
47
42
  description: Ruby port of Dropboxs zxcvbn.js
@@ -52,10 +47,14 @@ executables: []
52
47
  extensions: []
53
48
  extra_rdoc_files: []
54
49
  files:
55
- - .gitignore
56
- - .rspec
50
+ - ".github/workflows/ci.yml"
51
+ - ".gitignore"
52
+ - ".rspec"
53
+ - CHANGELOG.md
54
+ - CODE_OF_CONDUCT.md
57
55
  - Gemfile
58
- - LICENSE
56
+ - Guardfile
57
+ - LICENSE.txt
59
58
  - README.md
60
59
  - Rakefile
61
60
  - data/adjacency_graphs.json
@@ -69,6 +68,8 @@ files:
69
68
  - lib/zxcvbn/data.rb
70
69
  - lib/zxcvbn/dictionary_ranker.rb
71
70
  - lib/zxcvbn/entropy.rb
71
+ - lib/zxcvbn/feedback.rb
72
+ - lib/zxcvbn/feedback_giver.rb
72
73
  - lib/zxcvbn/match.rb
73
74
  - lib/zxcvbn/matchers/date.rb
74
75
  - lib/zxcvbn/matchers/dictionary.rb
@@ -88,6 +89,7 @@ files:
88
89
  - lib/zxcvbn/tester.rb
89
90
  - lib/zxcvbn/version.rb
90
91
  - spec/dictionary_ranker_spec.rb
92
+ - spec/feedback_giver_spec.rb
91
93
  - spec/matchers/date_spec.rb
92
94
  - spec/matchers/dictionary_spec.rb
93
95
  - spec/matchers/digits_spec.rb
@@ -117,37 +119,36 @@ files:
117
119
  - spec/zxcvbn_spec.rb
118
120
  - zxcvbn-ruby.gemspec
119
121
  homepage: http://github.com/envato/zxcvbn-ruby
120
- licenses: []
121
- post_install_message:
122
+ licenses:
123
+ - MIT
124
+ metadata:
125
+ bug_tracker_uri: https://github.com/envato/zxcvbn-ruby/issues
126
+ changelog_uri: https://github.com/envato/zxcvbn-ruby/blob/HEAD/CHANGELOG.md
127
+ documentation_uri: https://github.com/envato/zxcvbn-ruby/blob/HEAD/README.md
128
+ homepage_uri: https://github.com/envato/zxcvbn-ruby
129
+ source_code_uri: https://github.com/envato/zxcvbn-ruby
130
+ post_install_message:
122
131
  rdoc_options: []
123
132
  require_paths:
124
133
  - lib
125
134
  required_ruby_version: !ruby/object:Gem::Requirement
126
- none: false
127
135
  requirements:
128
- - - ! '>='
136
+ - - ">="
129
137
  - !ruby/object:Gem::Version
130
- version: '0'
131
- segments:
132
- - 0
133
- hash: 3120558835973257605
138
+ version: '2.5'
134
139
  required_rubygems_version: !ruby/object:Gem::Requirement
135
- none: false
136
140
  requirements:
137
- - - ! '>='
141
+ - - ">="
138
142
  - !ruby/object:Gem::Version
139
143
  version: '0'
140
- segments:
141
- - 0
142
- hash: 3120558835973257605
143
144
  requirements: []
144
- rubyforge_project:
145
- rubygems_version: 1.8.23.2
146
- signing_key:
147
- specification_version: 3
145
+ rubygems_version: 3.2.3
146
+ signing_key:
147
+ specification_version: 4
148
148
  summary: ''
149
149
  test_files:
150
150
  - spec/dictionary_ranker_spec.rb
151
+ - spec/feedback_giver_spec.rb
151
152
  - spec/matchers/date_spec.rb
152
153
  - spec/matchers/dictionary_spec.rb
153
154
  - spec/matchers/digits_spec.rb