@kensio/yulin-aws-simulation 1.9.0 → 1.10.0

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
3
  "name": "yulin-aws-simulation",
4
- "version": "1.9.0",
4
+ "version": "1.10.0",
5
5
  "description": "How to test AWS code well with the @kensio/yulin in-process simulator.",
6
6
  "author": {
7
7
  "name": "Kensio Software",
package/README.md CHANGED
@@ -38,10 +38,10 @@ ambiguous with the suffix Secrets Manager appends to an ARN and advised against
38
38
  already reached production. It caught a wrongly computed Cognito `SECRET_HASH` the stub had happily
39
39
  accepted.
40
40
 
41
- **Match service errors by `name`, not `instanceof`.** The SDK exports its exception classes, which
42
- invites the wrong check. `instanceof` holds only while exactly one copy of the SDK is in play. It
43
- passes in production and fails against the simulator. `name` is what the wire carries, and is the
44
- check that is right in both places.
41
+ **Match service errors by `name`.** The SDK exports its exception classes, which invites the wrong
42
+ check. `instanceof` holds only while exactly one copy of the SDK is in play. It passes in production
43
+ and fails against the simulator. `name` is what the wire carries, and is the check that is right in
44
+ both places.
45
45
 
46
46
  **Expect refusals, and treat them as a feature.** Yulin refuses a property it cannot simulate, and
47
47
  never quietly ignores one, because silently accepting something that changes real behaviour is
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kensio/yulin-aws-simulation",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "description": "How to test AWS code well with the @kensio/yulin in-process simulator.",
5
5
  "keywords": [
6
6
  "aws",
@@ -17,7 +17,7 @@ This skill serves the `isolated-testing-style` skill, the general argument for s
17
17
  stubs.
18
18
 
19
19
  Yulin is deliberately flexible, and plenty of shapes work. What follows is the recommended way to
20
- get the most out of it, not a set of rules. Each one says what it buys. A situation that does not
20
+ get the most out of it, offered as guidance. Each one says what it buys. A situation that does not
21
21
  want that trade can go the other way knowingly.
22
22
 
23
23
  ## Use what Yulin already gives you
@@ -41,9 +41,9 @@ exercise, then assert by reading the simulation back. A wrapper around any of th
41
41
  one thing a reader of the test needs to see, and it has to be maintained forever after.
42
42
 
43
43
  If a sequence genuinely repeats, make it a small function in the same test file, and keep it
44
- returning the simulation objects themselves, not a bespoke shape of its own. The point at which it
45
- wants a class, an options interface, or a directory, it has stopped being test setup and become a
46
- second product.
44
+ returning the simulation objects themselves. A bespoke return shape starts hiding them. The point at
45
+ which it wants a class, an options interface, or a directory, it has stopped being test setup and
46
+ become a second product.
47
47
 
48
48
  ## One synthesized template, for tests, local dev and production
49
49
 
@@ -119,8 +119,8 @@ both already in production:
119
119
  - A Cognito `SECRET_HASH` computed the wrong way. The stub had accepted that too, because a stub is
120
120
  never going to verify a signature.
121
121
 
122
- Intercept the class, not the instance, in most cases, since the code under test usually constructs
123
- its own clients. Intercept an instance when only one client should reach the simulation.
122
+ Intercept the class in most cases, since the code under test usually constructs its own clients.
123
+ Intercept an instance when only one client should reach the simulation.
124
124
 
125
125
  Each `SimSdk` owns a `SimAws`, reachable as `simSdk.simAws` for seeding and inspecting state. Pass
126
126
  an existing one with `new SimSdk({ simAws })` to share.
@@ -129,8 +129,8 @@ an existing one with `new SimSdk({ simAws })` to share.
129
129
 
130
130
  Interception replaces `send` on the thing it is given. It has to be given the client the code under
131
131
  test actually calls. The wrapper clients are where this bites. A `DynamoDBDocumentClient` built over
132
- a `DynamoDBClient` is what the code sends through. It is the document client that needs
133
- intercepting, not the client underneath it.
132
+ a `DynamoDBClient` is what the code sends through. The document client is the one that needs
133
+ intercepting.
134
134
 
135
135
  ```typescript
136
136
  using simSdk = new SimSdk();
@@ -200,7 +200,7 @@ This is where simulation pays off over stubs a second time. A call-count asserti
200
200
  today's implementation. A state assertion holds however the handler is rewritten, and it fails if
201
201
  the call was made in a way the real service would have rejected.
202
202
 
203
- ## Match service errors by name, not instanceof
203
+ ## Match service errors by name
204
204
 
205
205
  ```typescript
206
206
  // Wrong. Passes in production, fails against the simulator.
@@ -215,8 +215,8 @@ one copy of the SDK package is in play. Two copies in the module graph, a bundle
215
215
  raising its own classes, and it silently stops matching. Yulin's errors carry the service's real
216
216
  error names and SDK-shaped `$metadata`, but they are not instances of the SDK classes.
217
217
 
218
- This is worth fixing in production code, not worked around in tests. `name` is what the wire
219
- carries. The `name` check is the one that is right in both places. A version skew between two
218
+ This is worth fixing in production code, and working around it in tests hides it. `name` is what the
219
+ wire carries. The `name` check is the one that is right in both places. A version skew between two
220
220
  `@aws-sdk/client-*` packages breaks `instanceof` in production too, just less predictably than the
221
221
  simulator does.
222
222
 
@@ -232,7 +232,7 @@ properties from the synthesized template until it deploys, keeping a list, then
232
232
  upstream.
233
233
 
234
234
  ```typescript
235
- // A throwaway transform used to find the floor, not to keep.
235
+ // A throwaway transform used to find the floor. Delete it afterwards.
236
236
  function stripUntilItDeploys(template: CfnTemplateBodyRecord): CfnTemplateBodyRecord {
237
237
  // Remove one refused property, re-run, record the next refusal, repeat.
238
238
  // Keep the list. Raise it as one issue.
@@ -249,9 +249,8 @@ trusting a test that depends on the setting.
249
249
 
250
250
  ## Raise gaps upstream, and weight false passes far above false refusals
251
251
 
252
- Fix gaps on [the Yulin repository](https://github.com/KensioSoftware/yulin) rather than working
253
- around them locally. A local workaround has to be maintained in every project that hits the same
254
- gap.
252
+ Fix gaps on [the Yulin repository](https://github.com/KensioSoftware/yulin) at source. A local
253
+ workaround has to be maintained in every project that hits the same gap.
255
254
 
256
255
  When reporting, the asymmetry matters more than the volume:
257
256
 
@@ -272,7 +271,7 @@ with the property and the template that carries it.
272
271
 
273
272
  Vitest gives each test file its own worker, so module-level state is already isolated between files.
274
273
  Deploy a stack once for the file and let the tests share it. Isolation inside the file comes from
275
- randomised names, not from rebuilding the environment.
274
+ randomised names. Rebuilding the environment buys nothing.
276
275
 
277
276
  ```typescript
278
277
  let simAws: SimAws;
@@ -303,9 +302,9 @@ same state is the beginning of the harness this skill opens by arguing against.
303
302
 
304
303
  ## Run the handler as a real simulated Lambda
305
304
 
306
- Yulin can run an in-process handler as a function in the simulation, rather than calling it
307
- directly. Its SDK calls are routed into the simulation as the execution role. The IAM policies in
308
- the template are exercised too.
305
+ Yulin can run an in-process handler as a function inside the simulation, in place of a direct call
306
+ from the test. Its SDK calls are routed into the simulation as the execution role. The IAM policies
307
+ in the template are exercised too.
309
308
 
310
309
  Bind a handler to a template function at deploy time with `bindings`:
311
310