sql_matchers 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4f1773fdab03f1f4a89f6b58bcdaeb0833ab5666836cd7536acd4627f65e9618
4
+ data.tar.gz: ba267a8def94f0e7579e9d0be92dead4504ec0c2a8f02f5d92cc3991adf9f840
5
+ SHA512:
6
+ metadata.gz: adf3277acce82bff99919c98242e3aa8dd83145fd3db5349bfc3ee34e07bb1fae2815cb68f0edc33342b0758a64a2d346ede745a21f7f97e1f1e4241e0c16365
7
+ data.tar.gz: 35980c31136c6b60c3f462376fc502f752dbf692de108ce38cde0ef9f3d8e56d5618caaad54f861a7b026403784a5a6820d0531f5ad3afb06c815f7fa0e382e0
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ # Changelog
2
+
3
+ ## [Unreleased]
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,33 @@
1
+ ## Security issues
2
+
3
+ If you have found a security related issue, please do not file an issue on
4
+ GitHub or send a PR addressing the issue. Contact [Keygen](mailto:security@keygen.sh)
5
+ directly. You will be given public credit for your disclosure.
6
+
7
+ ## Reporting issues
8
+
9
+ Please try to answer the following questions in your bug report:
10
+
11
+ - What did you do?
12
+ - What did you expect to happen?
13
+ - What happened instead?
14
+
15
+ Make sure to include as much relevant information as possible. Ruby version,
16
+ Rails version, `sql_matchers` version, OS version and any stack traces
17
+ you have are very valuable.
18
+
19
+ ## Pull Requests
20
+
21
+ - **Add tests!** Your patch won't be accepted if it doesn't have tests.
22
+
23
+ - **Document any change in behaviour**. Make sure the README and any other
24
+ relevant documentation are kept up-to-date.
25
+
26
+ - **Create topic branches**. Please don't ask us to pull from your master branch.
27
+
28
+ - **One pull request per feature**. If you want to do more than one thing, send
29
+ multiple pull requests.
30
+
31
+ - **Send coherent history**. Make sure each individual commit in your pull
32
+ request is meaningful. If you had to make multiple intermediate commits while
33
+ developing, please squash them before sending them to us.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2024 Keygen LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,131 @@
1
+ # sql_matchers
2
+
3
+ [![CI](https://github.com/keygen-sh/sql_matchers/actions/workflows/test.yml/badge.svg)](https://github.com/keygen-sh/sql_matchers/actions)
4
+ [![Gem Version](https://badge.fury.io/rb/sql_matchers.svg)](https://badge.fury.io/rb/sql_matchers)
5
+
6
+ Use `sql_matchers` to create temporary tables and models in RSpec specs,
7
+ rather than create and maintain a dummy Rails application or messy block-level
8
+ constants.
9
+
10
+ This gem was extracted from [Keygen](https://keygen.sh).
11
+
12
+ Sponsored by:
13
+
14
+ <a href="https://keygen.sh?ref=sql_matchers">
15
+ <div>
16
+ <img src="https://keygen.sh/images/logo-pill.png" width="200" alt="Keygen">
17
+ </div>
18
+ </a>
19
+
20
+ _A fair source software licensing and distribution API._
21
+
22
+ ## Installation
23
+
24
+ Add this line to your application's `Gemfile`:
25
+
26
+ ```ruby
27
+ gem 'sql_matchers'
28
+ ```
29
+
30
+ And then execute:
31
+
32
+ ```bash
33
+ $ bundle
34
+ ```
35
+
36
+ Or install it yourself as:
37
+
38
+ ```bash
39
+ $ gem install sql_matchers
40
+ ```
41
+
42
+ ## Usage
43
+
44
+ ### `temporary_table`
45
+
46
+ To define a temporary table:
47
+
48
+ ```ruby
49
+ describe Example do
50
+ temporary_table :user do |t|
51
+ t.string :email
52
+ t.string :first_name
53
+ t.string :last_name
54
+ t.index :email, unique: true
55
+ end
56
+
57
+ it 'should define a table' do
58
+ expect(ActiveRecord::Base.connection.table_exists?(:user)).to be true
59
+ end
60
+ end
61
+ ```
62
+
63
+ The full Active Record schema API is available.
64
+
65
+ ### `temporary_model`
66
+
67
+ To define an Active Record:
68
+
69
+ ```ruby
70
+ describe Example do
71
+ temporary_model :user do
72
+ has_many :posts
73
+ end
74
+
75
+ it 'should define a record' do
76
+ expect(const_defined?(:User)).to be true
77
+ end
78
+ end
79
+ ```
80
+
81
+ To define an Active Model:
82
+
83
+ ```ruby
84
+ describe Example do
85
+ temporary_model :guest_user, table_name: nil, base_class: nil do
86
+ include ActiveModel::Model
87
+ end
88
+
89
+ it 'should define a model' do
90
+ expect(const_defined?(:GuestUser)).to be true
91
+ end
92
+ end
93
+ ```
94
+
95
+ To define a PORO:
96
+
97
+ ```ruby
98
+ describe Example do
99
+ temporary_model :null_user, table_name: nil, base_class: nil do
100
+ # ...
101
+ end
102
+
103
+ it 'should define a PORO' do
104
+ expect(const_defined?(:NullUser)).to be true
105
+ end
106
+ end
107
+ ```
108
+
109
+ ## Future
110
+
111
+ Right now, the gem only supports RSpec, but we're open to pull requests that
112
+ extend the functionality to other testing frameworks.
113
+
114
+ ## Supported Rubies
115
+
116
+ **`sql_matchers` supports Ruby 3.1 and above.** We encourage you to upgrade
117
+ if you're on an older version. Ruby 3 provides a lot of great features, like
118
+ better pattern matching and a new shorthand hash syntax.
119
+
120
+ ## Is it any good?
121
+
122
+ Yes.
123
+
124
+ ## Contributing
125
+
126
+ If you have an idea, or have discovered a bug, please open an issue or create a
127
+ pull request.
128
+
129
+ ## License
130
+
131
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/SECURITY.md ADDED
@@ -0,0 +1,8 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a vulnerability
4
+
5
+ If you find a vulnerability in `sql_matchers`, please contact Keygen via
6
+ [email](mailto:security@keygen.sh).
7
+
8
+ You will be given public credit for your disclosure.
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SqlMatchers
4
+ module Loggers
5
+ class Query
6
+ IGNORED_STATEMENTS = %w[CACHE SCHEMA]
7
+ IGNORED_STATEMENT_RE = %r{^(?:ROLLBACK|BEGIN|COMMIT|SAVEPOINT|RELEASE)}
8
+ IGNORED_COMMENT_RE = %r{
9
+ /\*(\w+='\w+',?)+\*/ # query log tags
10
+ }x
11
+
12
+ def initialize
13
+ @queries = []
14
+ end
15
+
16
+ def self.subscribe(&) = new.subscribe(&)
17
+ def subscribe(&block)
18
+ ActiveSupport::Notifications.subscribed(
19
+ logger_proc,
20
+ 'sql.active_record',
21
+ &proc {
22
+ result = block.call
23
+ result.load if result in ActiveRecord::Relation # autoload relations
24
+ }
25
+ )
26
+
27
+ @queries
28
+ end
29
+
30
+ private
31
+
32
+ def logger_proc = proc(&method(:logger))
33
+ def logger(event)
34
+ unless IGNORED_STATEMENTS.include?(event.payload[:name]) || IGNORED_STATEMENT_RE.match(event.payload[:sql])
35
+ query = event.payload[:sql].gsub(IGNORED_COMMENT_RE, '')
36
+ .squish
37
+
38
+ @queries << query
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SqlMatchers
4
+ module Loggers; end
5
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../loggers/query'
4
+
5
+ module SqlMatchers
6
+ module Matchers
7
+ class Query
8
+ def initialize(count: nil, &block)
9
+ @count = count
10
+ @block = block
11
+ end
12
+
13
+ def supports_block_expectations? = true
14
+ def supports_value_expectations? = true
15
+
16
+ def matches?(block)
17
+ @queries = Loggers::Query.subscribe(&block)
18
+
19
+ (@count.nil? || @queries.size == @count) && (
20
+ @block.nil? || @block.call(@queries)
21
+ )
22
+ end
23
+
24
+ def failure_message
25
+ "expected to match #{@count} queries but got #{@queries.size}"
26
+ end
27
+
28
+ def failure_message_when_negated
29
+ "expected to not match #{@count} queries"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'anbt-sql-formatter/formatter'
4
+
5
+ module SqlMatchers
6
+ module Matchers
7
+ class Sql
8
+ attr_reader :actual, :expected
9
+
10
+ def initialize(expected)
11
+ @expected = expected
12
+ @formatter = AnbtSql::Formatter.new(
13
+ AnbtSql::Rule.new.tap do |r|
14
+ r.keyword = AnbtSql::Rule::KEYWORD_UPPER_CASE
15
+ r.function_names += %w[count sum substr date]
16
+ r.indent_string = ' '
17
+ end
18
+ )
19
+ end
20
+
21
+ def diffable? = true
22
+ def matches?(actual)
23
+ @expected = formatter.format(+expected.to_s.strip)
24
+ @actual = formatter.format(+actual.to_s.strip)
25
+
26
+ @actual == @expected
27
+ end
28
+
29
+ def failure_message
30
+ <<~MSG
31
+ Expected SQL to match:
32
+ expected:
33
+ #{@expected.squish}
34
+ got:
35
+ #{@actual.squish}
36
+ MSG
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :formatter
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'matchers/query'
4
+ require_relative 'matchers/sql'
5
+
6
+ module SqlMatchers
7
+ module Matchers
8
+ def match_query(...) = Query.new(...)
9
+ def match_queries(...) = match_query(...)
10
+ def match_sql(...) = Sql.new(...)
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'matchers'
4
+
5
+ module SqlMatchers
6
+ module Methods
7
+ include Matchers
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SqlMatchers
4
+ VERSION = '0.0.1'
5
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_record'
4
+
5
+ require_relative 'sql_matchers/methods'
6
+ require_relative 'sql_matchers/version'
7
+
8
+ module SqlMatchers; end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sql_matchers
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Zeke Gabrielse
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-08-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '6.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: anbt-sql-formatter
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: temporary_tables
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.0.0.pre.rc.1
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.0.pre.rc.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.4'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.4'
69
+ description: Query and SQL matchers for RSpec.
70
+ email:
71
+ - oss@keygen.sh
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - CHANGELOG.md
77
+ - CONTRIBUTING.md
78
+ - LICENSE
79
+ - README.md
80
+ - SECURITY.md
81
+ - lib/sql_matchers.rb
82
+ - lib/sql_matchers/loggers.rb
83
+ - lib/sql_matchers/loggers/query.rb
84
+ - lib/sql_matchers/matchers.rb
85
+ - lib/sql_matchers/matchers/query.rb
86
+ - lib/sql_matchers/matchers/sql.rb
87
+ - lib/sql_matchers/methods.rb
88
+ - lib/sql_matchers/version.rb
89
+ homepage: https://github.com/keygen-sh/sql_matchers
90
+ licenses:
91
+ - MIT
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '3.1'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubygems_version: 3.4.13
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Query and SQL matchers for RSpec.
112
+ test_files: []