ts_schema_spec 0.5.4 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8202e8af0fa27c82203f869cd593208ee48dd95bfe23f6ab53083c47442fc47
4
- data.tar.gz: 3afcb839cc834657613896897ba454234a07facc8b0ffc3a9e8ce54abea5dffb
3
+ metadata.gz: e3c86744b3644ad258aa39eff8ff11b55df1cc933003276126f7b1b3d9952d91
4
+ data.tar.gz: e0a59266d59248a00e092c96b85978bde02bf19d1dd85f6b382addc3ca9fb32b
5
5
  SHA512:
6
- metadata.gz: a4608416aebf93c1125f9df04126b44479f52bf95e7605f924aa14af04b18fbafef30f39e3cf0ff16c38b948d9f970b37fb552b867cb9725764d569b83cdb1d4
7
- data.tar.gz: 8ff1849e182079b473b130922e9315dfc92766c5d84bad559d52e715c01e3ffbc86effafa971b445f2fc2ee307a6819be81f45266d9441c07333c0f658b38600
6
+ metadata.gz: dbcc3f50c232a8cf847db8804abc4af17140f884c051b414fea6f6cd56d0f93127c2e002b2856c255305dc3685b236329dd2a58dc6e552f99dc11b6d441ccd4d
7
+ data.tar.gz: 83f7161eebc10dd01d0634fa4eb022c7d5afa5f8ace26690bfa5022c5fa624409f167497dcaf9c2ef2cd3b05ea452dccf7124bd64581c5cba456b162cad2fc97
data/README.md CHANGED
@@ -8,7 +8,7 @@ Built for RSpec, but could be ported to other test frameworks (Minitest, etc.).
8
8
  `react_component_props`, an optional React-specific helper, reads props out of
9
9
  rendered mounts.
10
10
 
11
- React is the case this gem was built for, not a requirement. `match_schema`
11
+ React is the case this gem was built for, not a requirement. `match_ts_schema`
12
12
  checks any payload against any exported TypeScript type, so a Stimulus
13
13
  controller or a plain fetch client works the same way.
14
14
 
@@ -16,7 +16,7 @@ controller or a plain fetch client works the same way.
16
16
 
17
17
  ```ruby
18
18
  # Gemfile
19
- gem "ts_schema_spec", github: "nitidbit/ts_schema_spec", tag: "v0.5.3", group: :test
19
+ gem "ts_schema_spec", group: :test
20
20
  ```
21
21
 
22
22
  This gem requires ts-json-schema-generator, resolved from your project's
@@ -75,7 +75,7 @@ RAILS_ENV=test bundle exec rake ts_schema_spec:install_skill
75
75
 
76
76
  `RAILS_ENV=test` is required when the gem is in `group: :test`, as above.
77
77
 
78
- It lands in `.claude/skills/react-prop-type-spec/SKILL.md`, stamped with the
78
+ It lands in `.claude/skills/ts-schema-spec/SKILL.md`, stamped with the
79
79
  gem version. To keep the skill in sync with the gem version:
80
80
 
81
81
  ```ruby
@@ -85,6 +85,9 @@ it "has the skill matching the installed gem" do
85
85
  end
86
86
  ```
87
87
 
88
+ Versions up to 0.5.4 named the skill `react-prop-type-spec`. After reinstalling,
89
+ delete `.claude/skills/react-prop-type-spec/`.
90
+
88
91
  ## Use
89
92
 
90
93
  ### A JSON endpoint
@@ -98,7 +101,7 @@ it "matches AccountPayload" do
98
101
 
99
102
  expect(response).to be_successful
100
103
  expect(response.parsed_body["accounts"])
101
- .to match_schema("app/javascript/types/account.ts", "AccountPayload")
104
+ .to match_ts_schema("app/javascript/types/account.ts", "AccountPayload")
102
105
  end
103
106
  ```
104
107
 
@@ -131,29 +134,32 @@ describe "the props handed to RoleMatrix" do
131
134
 
132
135
  expect(response).to be_successful
133
136
  props = react_component_props("RoleMatrix")
134
- expect(props).to match_schema(role_matrix, "RoleMatrixProps")
137
+ expect(props).to match_ts_schema(role_matrix, "RoleMatrixProps")
135
138
  end
136
139
  end
137
140
  ```
138
141
 
139
- `match_schema` accepts a hash or an array of hashes. Given an array, it
142
+ `match_ts_schema` accepts a hash or an array of hashes. Given an array, it
140
143
  validates every item and fails on an empty one — in both directions, so
141
- `to_not match_schema` does not pass vacuously either. A page that stopped
144
+ `to_not match_ts_schema` does not pass vacuously either. A page that stopped
142
145
  rendering the component fails rather than passing silently. The alternative
143
- construction, `expect(props).to all match_schema(...)`, would pass on an empty
144
- array.
146
+ construction, `expect(props).to all match_ts_schema(...)`, would pass on an
147
+ empty array.
145
148
 
146
149
  ## API
147
150
 
148
151
  | Call | Returns |
149
152
  | --------------------------------------- | ----------------------------------------------------------- |
150
153
  | `TsSchemaSpec.schema_for(path, type)` | a `JSONSchemer` schema scoped to that exported type |
151
- | `match_schema(path, type)` | matcher; validates a hash, or every item of an array |
154
+ | `match_ts_schema(path, type)` | matcher; validates a hash, or every item of an array |
152
155
  | `react_component_props(name[, html])` | array of props hashes, one per mount |
153
156
  | `TsSchemaSpec::Skill.check!(root)` | raises if the installed skill is stale or missing |
154
157
  | `TsSchemaSpec.configure` | sets `tsconfig` and extra generator arguments |
155
158
  | `TsSchemaSpec.clear_cache!` | drops the generated-schema cache |
156
159
 
160
+ `match_ts_schema` was called `match_schema` before 0.6.1. The old name still
161
+ works but is deprecated and will be removed.
162
+
157
163
  `path` is resolved from wherever the suite runs, which is the Rails root in
158
164
  practice. Name the type at the assertion, so an example says which type it is
159
165
  checking. When several examples read the same source, bind the path to a local
@@ -205,8 +211,8 @@ generator, a shared JSON file, whatever suits your repo. That is outside this
205
211
  gem's scope, but with one in place, and a record for each value in the
206
212
  example, a drifted union fails here rather than in the browser.
207
213
 
208
- **Pass the whole collection.** `match_schema` validates every item and fails
209
- on an empty one. Avoid `expect(props).to all match_schema(...)`, which
214
+ **Pass the whole collection.** `match_ts_schema` validates every item and fails
215
+ on an empty one. Avoid `expect(props).to all match_ts_schema(...)`, which
210
216
  passes on an empty array, hiding an issue with generation.
211
217
 
212
218
  **Assert the response is successful first.** Otherwise a redirect or a 500
@@ -66,7 +66,7 @@ module TsSchemaSpec
66
66
  end
67
67
  end
68
68
 
69
- RSpec::Matchers.define :match_schema do |source, type|
69
+ RSpec::Matchers.define :match_ts_schema do |source, type|
70
70
  def validation_errors(actual, source, type)
71
71
  schema = TsSchemaSpec.schema_for(source, type)
72
72
  @errors = TsSchemaSpec::Matching.errors(schema, actual)
@@ -81,7 +81,7 @@ RSpec::Matchers.define :match_schema do |source, type|
81
81
 
82
82
  Usually the component was not rendered on the page, or no records
83
83
  existed for the endpoint to serialize. If an empty result is what you
84
- meant to assert, use `be_empty` or `eq([])` — match_schema on an empty
84
+ meant to assert, use `be_empty` or `eq([])` — match_ts_schema on an empty
85
85
  collection checks nothing.
86
86
  MSG
87
87
  end
@@ -121,3 +121,12 @@ RSpec::Matchers.define :match_schema do |source, type|
121
121
  "expected the payload not to match #{type} (#{source}), but it did:\n#{JSON.pretty_generate(actual)}"
122
122
  end
123
123
  end
124
+
125
+ module RSpec
126
+ module Matchers
127
+ def match_schema(...)
128
+ RSpec.deprecate("match_schema", replacement: "match_ts_schema")
129
+ match_ts_schema(...)
130
+ end
131
+ end
132
+ end
@@ -9,7 +9,7 @@ module TsSchemaSpec
9
9
  # silently outdated copy teaches the wrong API. The copy carries the gem
10
10
  # version and `check!` fails when the two diverge.
11
11
  module Skill
12
- NAME = "react-prop-type-spec"
12
+ NAME = "ts-schema-spec"
13
13
  INSTALL_PATH = ".claude/skills/#{NAME}/SKILL.md"
14
14
  SOURCE_PATH = File.expand_path("../../skills/#{NAME}/SKILL.md", __dir__)
15
15
  STAMP = "ts_schema_spec_version"
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  namespace :ts_schema_spec do
4
- desc "Copy the react-prop-type-spec agent skill into .claude/skills"
4
+ desc "Copy the ts-schema-spec agent skill into .claude/skills"
5
5
  task :install_skill do
6
6
  require "ts_schema_spec/skill"
7
7
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TsSchemaSpec
4
- VERSION = "0.5.4"
4
+ VERSION = "0.6.1"
5
5
  end
@@ -1,7 +1,7 @@
1
1
  ---
2
- name: react-prop-type-spec
2
+ name: ts-schema-spec
3
3
  description: >
4
- Write or update RSpec tests that use match_schema to verify a Rails
4
+ Write or update RSpec tests that use match_ts_schema to verify a Rails
5
5
  endpoint's payload matches the TypeScript type that consumes it. TRIGGER
6
6
  automatically (without being asked) whenever data crossing from Ruby to
7
7
  TypeScript is added or changed: adding a controller action; changing
@@ -9,9 +9,9 @@ description: >
9
9
  associations); adding or renaming a key in a render json: response or in
10
10
  props handed to a component; converting a Rails-mounted component from .jsx
11
11
  to .tsx; deleting a component's propTypes; or rendering an already-typed
12
- component from an action that has no match_schema spec. React is the common
12
+ component from an action that has no match_ts_schema spec. React is the common
13
13
  case, not a requirement — a Stimulus controller or a plain fetch client
14
- reading the payload counts the same. Invoked as /react-prop-type-spec.
14
+ reading the payload counts the same. Invoked as /ts-schema-spec.
15
15
  ---
16
16
 
17
17
  A spec is owed any time data is handed from Ruby to TypeScript — not only when
@@ -19,15 +19,15 @@ something changes, and including where there is no Ruby diff at all. Two rules
19
19
  keep that from multiplying:
20
20
 
21
21
  - **Repeated mounts of one component are a single example.**
22
- `react_component_props` returns every mount and `match_schema` checks each.
22
+ `react_component_props` returns every mount and `match_ts_schema` checks each.
23
23
  - **Assert on the component Rails mounts.** A child receiving props from its
24
24
  parent is covered transitively; use the parent's props type.
25
25
 
26
26
  ## Step 0 — Already covered?
27
27
 
28
- Covered = the spec for **the action rendering it** has a `match_schema` example
29
- on that component. A sibling component, or the same component from another
30
- action, is not coverage. Covered → stop.
28
+ Covered = the spec for **the action rendering it** has a `match_ts_schema`
29
+ example on that component. A sibling component, or the same component from
30
+ another action, is not coverage. Covered → stop.
31
31
 
32
32
  ## Step 1 — Find the TypeScript consumer
33
33
 
@@ -71,7 +71,7 @@ implying the spec covers them.
71
71
  | `react_component` | `react_component_props("ComponentName")` |
72
72
 
73
73
  `react_component_props` returns **an array**, one entry per mount, and needs
74
- `render_views`. Pass it straight to `match_schema`: it validates every entry
74
+ `render_views`. Pass it straight to `match_ts_schema`: it validates every entry
75
75
  and fails on an empty collection. Never wrap it in `all`, which iterates zero
76
76
  times on an empty array and asserts nothing.
77
77
 
@@ -87,7 +87,7 @@ describe "the props handed to MyComponent" do
87
87
 
88
88
  expect(response).to be_successful
89
89
  props = react_component_props("MyComponent")
90
- expect(props).to match_schema("app/javascript/MyComponent.tsx", "MyComponentProps")
90
+ expect(props).to match_ts_schema("app/javascript/MyComponent.tsx", "MyComponentProps")
91
91
  end
92
92
  end
93
93
  ```
@@ -100,12 +100,12 @@ Rules:
100
100
  - Build multiple records with different traits, so optional fields, enum values
101
101
  and nil associations are actually exercised. Use existing factory traits.
102
102
  - Assert `response` is successful before asserting shape.
103
- - Let `match_schema` do the shape checking; no hand-written field assertions.
103
+ - Let `match_ts_schema` do the shape checking; no hand-written field assertions.
104
104
  - Several components in one action: an example each, or one example marked
105
105
  `:aggregate_failures` if rendering the page is expensive — without it the
106
106
  first mismatch hides the rest.
107
107
  - Do not write a spec that only checks `response.status`, and do not duplicate
108
- an existing `match_schema` for the same action.
108
+ an existing `match_ts_schema` for the same action.
109
109
  - **When it fails, fix Rails.** The type is the consumer's contract: if the
110
110
  component needs a field, the payload is wrong. Loosening the type is always
111
111
  the quicker route to green, and it is how this stops catching anything.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ts_schema_spec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vernon Coffey
@@ -60,13 +60,13 @@ files:
60
60
  - lib/ts_schema_spec/skill.rb
61
61
  - lib/ts_schema_spec/tasks/ts_schema_spec.rake
62
62
  - lib/ts_schema_spec/version.rb
63
- - skills/react-prop-type-spec/SKILL.md
63
+ - skills/ts-schema-spec/SKILL.md
64
64
  homepage: https://github.com/nitidbit/ts_schema_spec
65
65
  licenses:
66
66
  - MIT
67
67
  metadata:
68
- homepage_uri: https://github.com/nitidbit/ts_schema_spec
69
68
  source_code_uri: https://github.com/nitidbit/ts_schema_spec
69
+ bug_tracker_uri: https://github.com/nitidbit/ts_schema_spec/issues
70
70
  rubygems_mfa_required: 'true'
71
71
  rdoc_options: []
72
72
  require_paths: