@rotorsoft/act-tck 1.19.2 → 1.19.3

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.
package/dist/index.js CHANGED
@@ -798,7 +798,8 @@ import {
798
798
  ConcurrencyError,
799
799
  InMemoryCache,
800
800
  SNAP_EVENT as SNAP_EVENT2,
801
- TOMBSTONE_EVENT
801
+ TOMBSTONE_EVENT,
802
+ ValidationError
802
803
  } from "@rotorsoft/act";
803
804
  import { afterAll as afterAll4, beforeAll as beforeAll4, describe as describe8, expect as expect8, it as it7 } from "vitest";
804
805
  var runStoreTck = (options) => {
@@ -1155,6 +1156,94 @@ var runStoreTck = (options) => {
1155
1156
  expect8(got.map((e) => e.stream).sort()).toEqual([a, b].sort());
1156
1157
  });
1157
1158
  });
1159
+ describe8("stream filter grammar", () => {
1160
+ const seed_streams = async (streams) => {
1161
+ for (const s of streams)
1162
+ await store.commit(
1163
+ s,
1164
+ [inc(1)],
1165
+ make_meta({ stream: s })
1166
+ );
1167
+ };
1168
+ const streams_matching = async (pattern) => (await collect(store, { stream: pattern })).map((e) => e.stream).sort();
1169
+ const match_exactly_or_throw = async (pattern, expected) => {
1170
+ let matched;
1171
+ let error;
1172
+ try {
1173
+ matched = await streams_matching(pattern);
1174
+ } catch (e) {
1175
+ error = e;
1176
+ }
1177
+ if (error !== void 0) expect8(error).toBeInstanceOf(ValidationError);
1178
+ else expect8(matched).toEqual(expected.sort());
1179
+ };
1180
+ it7("portable subset: anchors, `.`, and `.*` match identically", async () => {
1181
+ const tag = uid();
1182
+ const plain = `g-${tag}-plain`;
1183
+ const dotted = `g-${tag}.dot`;
1184
+ const scored = `g-${tag}_us`;
1185
+ const pct = `g-${tag}%pc`;
1186
+ await seed_streams([plain, dotted, scored, pct]);
1187
+ expect8(await streams_matching(`^g-${tag}`)).toEqual(
1188
+ [plain, dotted, scored, pct].sort()
1189
+ );
1190
+ expect8(await streams_matching(`${tag}-plain$`)).toEqual([plain]);
1191
+ expect8(await streams_matching(`^g-${tag}-plain$`)).toEqual([plain]);
1192
+ expect8(await streams_matching(`^g-${tag}.dot$`)).toEqual([dotted]);
1193
+ expect8(await streams_matching(`^g-${tag}.plain$`)).toEqual([plain]);
1194
+ expect8(await streams_matching(`^g-${tag}.*dot$`)).toEqual([dotted]);
1195
+ });
1196
+ it7("literal `_` and `%` in patterns are not wildcards", async () => {
1197
+ const tag = uid();
1198
+ const scored = `u-${tag}_x`;
1199
+ const scored_decoy = `u-${tag}Zx`;
1200
+ const pct = `p-${tag}%y`;
1201
+ const pct_decoy = `p-${tag}ZZy`;
1202
+ await seed_streams([scored, scored_decoy, pct, pct_decoy]);
1203
+ expect8(await streams_matching(`^u-${tag}_x$`)).toEqual([scored]);
1204
+ expect8(await streams_matching(`^p-${tag}%y$`)).toEqual([pct]);
1205
+ });
1206
+ it7("portable subset applies to stream-position filters", async () => {
1207
+ const tag = uid();
1208
+ const scored = `sf-${tag}_a`;
1209
+ const decoy = `sf-${tag}Za`;
1210
+ await store.subscribe([{ stream: scored }, { stream: decoy }]);
1211
+ const got = [];
1212
+ await store.query_streams((p) => got.push(p.stream), {
1213
+ stream: `^sf-${tag}_a$`
1214
+ });
1215
+ expect8(got).toEqual([scored]);
1216
+ });
1217
+ it7("non-portable patterns match with full regex semantics or throw", async () => {
1218
+ const tag = uid();
1219
+ const a = `np-${tag}-a`;
1220
+ const b = `np-${tag}-b`;
1221
+ const c = `np-${tag}-c`;
1222
+ const one = `np-${tag}-1`;
1223
+ const aaa = `np-${tag}-aaa`;
1224
+ const dot = `e-${tag}.d`;
1225
+ const dot_decoy = `e-${tag}xd`;
1226
+ await seed_streams([a, b, c, one, aaa, dot, dot_decoy]);
1227
+ await match_exactly_or_throw(`^np-${tag}-(a|b)$`, [a, b]);
1228
+ await match_exactly_or_throw(`^np-${tag}-[0-9]$`, [one]);
1229
+ await match_exactly_or_throw(`^np-${tag}-a+$`, [a, aaa]);
1230
+ await match_exactly_or_throw(`^e-${tag}\\.d$`, [dot]);
1231
+ });
1232
+ it7("bulk stream ops reject non-portable filters instead of mis-matching", async () => {
1233
+ const tag = uid();
1234
+ const s = `bo-${tag}-a`;
1235
+ await store.subscribe([{ stream: s }]);
1236
+ let count;
1237
+ let error;
1238
+ try {
1239
+ count = await store.reset({ stream: `^bo-${tag}-(a|b)$` });
1240
+ } catch (e) {
1241
+ error = e;
1242
+ }
1243
+ if (error !== void 0) expect8(error).toBeInstanceOf(ValidationError);
1244
+ else expect8(count).toBe(1);
1245
+ });
1246
+ });
1158
1247
  describe8("subscribe + claim + ack", () => {
1159
1248
  it7("subscribes new streams and is idempotent on repeat", async () => {
1160
1249
  const s = `sub-${uid()}`;