@thisisagile/easy-test-react 21.0.0 → 21.0.2

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.
Files changed (2) hide show
  1. package/README.md +44 -19
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -85,21 +85,45 @@ Secondly, in most languages (Java not included), enumerations only have two prop
85
85
 
86
86
  Thirdly, and perhaps the most dangerous one, if you persist your enumerables to a storage facility (a database for instance), enumerations are usually stored using their index. This makes the data hard to interpret. After all, what does scope `2` really mean? But even worse, if you would add more items to your enumerable later on, the index of the items might alter, and hence the stored data gets a different meaning, often without noticing.
87
87
 
88
- Therefore, **easy** provides an `Enum` class, which is both extendable and allows you to define meaningful identifiers for your items, and also add additional properties. And still, the behaviour of enumerables created using the `Enum` class, is comparable to traditional enumerables. Here's the `UseCase` enumerable from **easy** as an example.
89
-
90
- export class UseCase extends Enum {
91
- constructor(readonly scope: Scope, name: string, id: string = text(name).kebab) {
92
- super(name, id);
93
- }
94
-
95
- static readonly Main = new UseCase(Scope.Basic, "Main");
96
- static readonly Login = new UseCase(Scope.Auth, "Login");
97
- static readonly Logout = new UseCase(Scope.Auth, "Logout");
98
- static readonly ForgotPassword = new UseCase(Scope.Auth, "Forgot password");
99
- static readonly ChangePassword = new UseCase(Scope.Auth, "Change password");
100
- }
88
+ Therefore, **easy** provides an `Enum` class, which is both extendable and allows you to define meaningful identifiers for your items, and also add additional properties. And still, the behaviour of enumerables created using the `Enum` class, is comparable to traditional enumerables.
89
+
90
+ A set of enumerables, such as all use cases of a service, is a catalogue: a module that exports each item as a constant, plus a registry to look items up. Catalogues are modules rather than classes with static members, so a bundler can drop the items you don't use. Here's a catalogue of use cases, built with the `UseCase` value class from **easy**.
91
+
92
+ // UseCase.ts
93
+ import * as App from '@thisisagile/easy/App';
94
+ import { create, type Enum } from '@thisisagile/easy/UseCase';
95
+ import { lazyRegistry, type Registry } from '@thisisagile/easy/types/Registry';
96
+ import * as Scope from './Scope';
97
+
98
+ export const Login = /* @__PURE__ */ create(App.Main, 'Login', 'login', [Scope.Auth]);
99
+ export const Logout = /* @__PURE__ */ create(App.Main, 'Logout', 'logout', [Scope.Auth]);
100
+ export const ChangePassword = /* @__PURE__ */ create(App.Main, 'Change password', 'change-password', [Scope.Auth]);
101
+
102
+ const registry = /* @__PURE__ */ lazyRegistry(() => ({ Login, Logout, ChangePassword }));
103
+ export const all: Registry<Enum>['all'] = () => registry.all();
104
+ export const byId: Registry<Enum>['byId'] = (id, alt) => registry.byId(id, alt);
105
+ export const byIds: Registry<Enum>['byIds'] = ids => registry.byIds(ids);
106
+ export const filter: Registry<Enum>['filter'] = (predicate, params) => registry.filter(predicate, params);
107
+ export const first: Registry<Enum>['first'] = (predicate, params) => registry.first(predicate, params);
108
+
109
+ The catalogue has three items, such as `UseCase.Login` or `UseCase.ChangePassword`. A `UseCase` has the additional properties `app` and `scopes`, which the `Enum` class does not have. To add properties of your own, extend the value class (`class MyUseCase extends Enum`) and export a `create` for it. All instances of `Enum` have a property `id`, which is used to store the enums, when used as property on entities, or for comparison. `byId()` turns a stored id back into its item.
101
110
 
102
- The class `UseCase` has five items, such as `UseCase.Main` or `UseCase.ChangePassword`. The constructor has an additional property `scope`, which the `Enum` class does not have, but it calls on the constructor of its superclass to actual make it work. All instances of `Enum` have a property `id`, which is used to store the enums, when used as property on entities, or for comparison.
111
+ Use a catalogue with a namespace import or with named imports:
112
+
113
+ import * as UseCase from './UseCase';
114
+ import { Login } from './UseCase';
115
+
116
+ UseCase.Login.equals(Login); // true
117
+ UseCase.byId('logout'); // UseCase.Logout
118
+
119
+ The catalogues that ship with **easy** are imported the same way, through their own subpath: `@thisisagile/easy/HttpStatus`, `ContentType`, `HttpVerb`, `Database`, `Environment`, `Exception`, `App`, `Scope` and `UseCase`, and `@thisisagile/easy-domain/Country`, `Currency`, `Locale`, `UnitOfMeasurement` and `UnitOfWeight`. These subpaths also offer a default export, so `import Locale from '@thisisagile/easy-domain/Locale'` works too.
120
+
121
+ To keep catalogues tree-shakeable, follow these rules:
122
+ - Mark every item `/* @__PURE__ */`, so an unused item can be dropped.
123
+ - Keep the registry in a constant and export `all`, `byId`, `byIds`, `filter` and `first` as functions, as above. Never write `export const { all, byId } = lazyRegistry(...)`: bundlers such as rolldown treat the destructuring as a side effect and keep every item.
124
+ - Prefer `import * as` or named imports. `Locale.EN` then keeps only `EN`, in webpack, Turbopack, rolldown/tsdown and esbuild/tsup alike. A default import shakes in webpack, Turbopack and rolldown, but esbuild (tsup) always keeps the whole catalogue.
125
+ - Calling `all()`, `byId()` or any other registry function keeps the whole catalogue, as it needs every item to answer.
126
+ - If you publish a catalogue with a default export, see [PACKAGING.md](PACKAGING.md) for how the build keeps it shakeable.
103
127
 
104
128
  ### Value objects
105
129
  When we are not so much interested in the identity of objects, as with entities, but are merely interested in the values of the object, we use value objects. A nice useful definition of value objects is presented by Eric Evens in his seminal book *Domain Driven Design*.
@@ -227,12 +251,13 @@ Because data in existing databases rarely supplies the format you need in your s
227
251
  }
228
252
  }
229
253
 
230
- The `Map` and `Table` classes have a property called `db` that represents the database to connect to. This is usually an instance of the `Database` enumeration, which in its turn defines the database (and its provider) to connect to, as in the example below.
254
+ The `Map` and `Table` classes have a property called `db` that represents the database to connect to. This is usually an item of a `Database` catalogue, which in its turn defines the database (and its provider) to connect to, as in the example below.
231
255
 
232
- export class MyDatabase extends Database {
233
- static readonly Erp = new Database('openerp', PostgreSqlProvider);
234
- static readonly Cms = new Database('cms', MySqlProvider);
235
- }
256
+ // MyDatabase.ts
257
+ import { create } from '@thisisagile/easy/Database';
258
+
259
+ export const Erp = /* @__PURE__ */ create('openerp', PostgreSqlProvider);
260
+ export const Cms = /* @__PURE__ */ create('cms', MySqlProvider);
236
261
 
237
262
  Next, the `Map`, `Table` and `Collection` classes, describe a list of properties that you would want mapped in the incoming JSON. Properties in the incoming JSON that are not described here are copied automatically. Properties can use converters, e.g. to converter from number to string and vice versa. Converters are bi-directional, as data that needs to go from the service to storage is mapped back to the database specific format too.
238
263
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thisisagile/easy-test-react",
3
- "version": "21.0.0",
3
+ "version": "21.0.2",
4
4
  "description": "Straightforward wrapper library for testing-library/react",
5
5
  "author": "Sander Hoogendoorn",
6
6
  "license": "MIT",
@@ -50,7 +50,7 @@
50
50
  "@testing-library/dom": "^10.4.0",
51
51
  "@testing-library/jest-dom": "^6.6.3",
52
52
  "@testing-library/react": "^16.3.0",
53
- "@thisisagile/easy": "^21.0.0",
53
+ "@thisisagile/easy": "^21.0.2",
54
54
  "@types/react": "^18.3.18",
55
55
  "react": "^18.3.1",
56
56
  "react-dom": "^18.3.1"