@barefootjs/test 0.5.0 → 0.5.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/dist/index.js +139 -29
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -187862,6 +187862,24 @@ function getSourceLocation(node, sourceFile, filePath) {
187862
187862
  }
187863
187863
  };
187864
187864
  }
187865
+ function membersToProperties(members, sourceFile) {
187866
+ return members.filter(import_typescript6.default.isPropertySignature).map((member) => ({
187867
+ name: propertyNameText(member.name, sourceFile),
187868
+ type: typeNodeToTypeInfo(member.type, sourceFile) ?? {
187869
+ kind: "unknown",
187870
+ raw: "unknown"
187871
+ },
187872
+ optional: !!member.questionToken,
187873
+ readonly: !!member.modifiers?.some((m) => m.kind === import_typescript6.default.SyntaxKind.ReadonlyKeyword)
187874
+ }));
187875
+ }
187876
+ function propertyNameText(name, sourceFile) {
187877
+ if (!name)
187878
+ return "";
187879
+ if (import_typescript6.default.isStringLiteral(name) || import_typescript6.default.isNumericLiteral(name))
187880
+ return name.text;
187881
+ return name.getText(sourceFile);
187882
+ }
187865
187883
  function typeNodeToTypeInfo(typeNode, sourceFile) {
187866
187884
  if (!typeNode)
187867
187885
  return null;
@@ -187899,18 +187917,21 @@ function typeNodeToTypeInfo(typeNode, sourceFile) {
187899
187917
  return {
187900
187918
  kind: "object",
187901
187919
  raw,
187902
- properties: typeNode.members.filter(import_typescript6.default.isPropertySignature).map((member) => ({
187903
- name: member.name?.getText(sourceFile) ?? "",
187904
- type: typeNodeToTypeInfo(member.type, sourceFile) ?? {
187905
- kind: "unknown",
187906
- raw: "unknown"
187907
- },
187908
- optional: !!member.questionToken,
187909
- readonly: !!member.modifiers?.some((m) => m.kind === import_typescript6.default.SyntaxKind.ReadonlyKeyword)
187910
- }))
187920
+ properties: membersToProperties(typeNode.members, sourceFile)
187911
187921
  };
187912
187922
  }
187913
187923
  if (import_typescript6.default.isTypeReferenceNode(typeNode)) {
187924
+ const refName = import_typescript6.default.isIdentifier(typeNode.typeName) ? typeNode.typeName.text : "";
187925
+ if ((refName === "Array" || refName === "ReadonlyArray") && typeNode.typeArguments?.length === 1) {
187926
+ return {
187927
+ kind: "array",
187928
+ raw,
187929
+ elementType: typeNodeToTypeInfo(typeNode.typeArguments[0], sourceFile) ?? {
187930
+ kind: "unknown",
187931
+ raw: "unknown"
187932
+ }
187933
+ };
187934
+ }
187914
187935
  return {
187915
187936
  kind: "interface",
187916
187937
  raw
@@ -189052,14 +189073,17 @@ function collectInterfaceDefinition(node, ctx) {
189052
189073
  kind: "interface",
189053
189074
  name: node.name.text,
189054
189075
  definition: node.getText(ctx.sourceFile),
189076
+ properties: membersToProperties(node.members, ctx.sourceFile),
189055
189077
  loc: getSourceLocation(node, ctx.sourceFile, ctx.filePath)
189056
189078
  });
189057
189079
  }
189058
189080
  function collectTypeAliasDefinition(node, ctx) {
189081
+ const properties = import_typescript7.default.isTypeLiteralNode(node.type) ? membersToProperties(node.type.members, ctx.sourceFile) : undefined;
189059
189082
  ctx.typeDefinitions.push({
189060
189083
  kind: "type",
189061
189084
  name: node.name.text,
189062
189085
  definition: node.getText(ctx.sourceFile),
189086
+ properties,
189063
189087
  loc: getSourceLocation(node, ctx.sourceFile, ctx.filePath)
189064
189088
  });
189065
189089
  }
@@ -190435,7 +190459,24 @@ var UNSUPPORTED_METHODS = new Set([
190435
190459
  "some",
190436
190460
  "forEach",
190437
190461
  "flatMap",
190438
- "flat"
190462
+ "flat",
190463
+ "split",
190464
+ "startsWith",
190465
+ "endsWith",
190466
+ "replace",
190467
+ "replaceAll",
190468
+ "repeat",
190469
+ "padStart",
190470
+ "padEnd",
190471
+ "charAt",
190472
+ "charCodeAt",
190473
+ "codePointAt",
190474
+ "normalize",
190475
+ "substring",
190476
+ "substr",
190477
+ "match",
190478
+ "matchAll",
190479
+ "search"
190439
190480
  ]);
190440
190481
  function parseExpression(expr) {
190441
190482
  const trimmed = expr.trim();
@@ -191297,7 +191338,7 @@ function checkSupport(expr) {
191297
191338
  return {
191298
191339
  supported: false,
191299
191340
  level: "L5_UNSUPPORTED",
191300
- reason: `Higher-order method '${methodName}()' requires client-side evaluation. Use @client directive or pre-compute in Go.`
191341
+ reason: `Method '${methodName}()' has no template lowering and requires client-side evaluation. Wrap the expression in /* @client */ to defer it to hydration, or pre-compute the value before rendering.`
191301
191342
  };
191302
191343
  }
191303
191344
  }
@@ -192681,6 +192722,23 @@ function containsJsxInExpression(node) {
192681
192722
  }
192682
192723
  return import_typescript11.default.forEachChild(node, containsJsxInExpression) ?? false;
192683
192724
  }
192725
+ function callsJsxHelper(node, ctx) {
192726
+ let found = false;
192727
+ const visit2 = (n) => {
192728
+ if (found)
192729
+ return;
192730
+ if (import_typescript11.default.isCallExpression(n) && import_typescript11.default.isIdentifier(n.expression)) {
192731
+ const name = n.expression.text;
192732
+ if (ctx.analyzer.jsxFunctions.has(name) || ctx.analyzer.jsxMultiReturnFunctions.has(name)) {
192733
+ found = true;
192734
+ return;
192735
+ }
192736
+ }
192737
+ import_typescript11.default.forEachChild(n, visit2);
192738
+ };
192739
+ visit2(node);
192740
+ return found;
192741
+ }
192684
192742
  function containsAwaitExpression(node) {
192685
192743
  if (import_typescript11.default.isAwaitExpression(node))
192686
192744
  return true;
@@ -192760,7 +192818,7 @@ function transformJsxExpression(expr, ctx, isClientOnly = false) {
192760
192818
  if (node.operatorToken.kind === import_typescript11.default.SyntaxKind.AmpersandAmpersandToken) {
192761
192819
  return transformLogicalAnd(node, ctx);
192762
192820
  }
192763
- if ((node.operatorToken.kind === import_typescript11.default.SyntaxKind.QuestionQuestionToken || node.operatorToken.kind === import_typescript11.default.SyntaxKind.BarBarToken) && containsJsxInExpression(node.right)) {
192821
+ if ((node.operatorToken.kind === import_typescript11.default.SyntaxKind.QuestionQuestionToken || node.operatorToken.kind === import_typescript11.default.SyntaxKind.BarBarToken) && (containsJsxInExpression(node.right) || callsJsxHelper(node.right, ctx))) {
192764
192822
  return transformNullishCoalescing(node, ctx);
192765
192823
  }
192766
192824
  return null;
@@ -193217,23 +193275,23 @@ function checkLoopKey(callback, ctx, isNested) {
193217
193275
  }
193218
193276
  while (import_typescript11.default.isParenthesizedExpression(body))
193219
193277
  body = body.expression;
193278
+ function checkJsxOperand(node) {
193279
+ let n = node;
193280
+ while (import_typescript11.default.isParenthesizedExpression(n))
193281
+ n = n.expression;
193282
+ if (import_typescript11.default.isJsxElement(n))
193283
+ checkOpening(n.openingElement);
193284
+ else if (import_typescript11.default.isJsxSelfClosingElement(n))
193285
+ checkOpening(n);
193286
+ }
193220
193287
  if (import_typescript11.default.isConditionalExpression(body)) {
193221
- const whenTrue = body.whenTrue;
193222
- const whenFalse = body.whenFalse;
193223
- let wt = whenTrue;
193224
- let wf = whenFalse;
193225
- while (import_typescript11.default.isParenthesizedExpression(wt))
193226
- wt = wt.expression;
193227
- while (import_typescript11.default.isParenthesizedExpression(wf))
193228
- wf = wf.expression;
193229
- if (import_typescript11.default.isJsxElement(wt))
193230
- checkOpening(wt.openingElement);
193231
- else if (import_typescript11.default.isJsxSelfClosingElement(wt))
193232
- checkOpening(wt);
193233
- if (import_typescript11.default.isJsxElement(wf))
193234
- checkOpening(wf.openingElement);
193235
- else if (import_typescript11.default.isJsxSelfClosingElement(wf))
193236
- checkOpening(wf);
193288
+ checkJsxOperand(body.whenTrue);
193289
+ checkJsxOperand(body.whenFalse);
193290
+ return;
193291
+ }
193292
+ if (import_typescript11.default.isBinaryExpression(body) && (body.operatorToken.kind === import_typescript11.default.SyntaxKind.AmpersandAmpersandToken || body.operatorToken.kind === import_typescript11.default.SyntaxKind.BarBarToken || body.operatorToken.kind === import_typescript11.default.SyntaxKind.QuestionQuestionToken)) {
193293
+ checkJsxOperand(body.left);
193294
+ checkJsxOperand(body.right);
193237
193295
  return;
193238
193296
  }
193239
193297
  if (import_typescript11.default.isJsxElement(body)) {
@@ -193256,6 +193314,38 @@ function loopBodyIsMultiRoot(children) {
193256
193314
  return false;
193257
193315
  return loopBodyIsMultiRoot(only.children);
193258
193316
  }
193317
+ function branchHasNoElement(node) {
193318
+ if (node.type === "element" || node.type === "component")
193319
+ return false;
193320
+ if (node.type === "conditional") {
193321
+ return branchHasNoElement(node.whenTrue) || branchHasNoElement(node.whenFalse);
193322
+ }
193323
+ if (node.type === "fragment") {
193324
+ const real = node.children.filter((c) => !(c.type === "text" && typeof c.value === "string" && !c.value.trim()));
193325
+ return real.length !== 1 || branchHasNoElement(real[0]);
193326
+ }
193327
+ return true;
193328
+ }
193329
+ function loopBodyItemConditional(children) {
193330
+ const real = children.filter((c) => !(c.type === "text" && typeof c.value === "string" && !c.value.trim()));
193331
+ if (real.length !== 1)
193332
+ return null;
193333
+ const only = real[0];
193334
+ if (only.type !== "conditional")
193335
+ return null;
193336
+ if (branchHasNoElement(only.whenTrue) || branchHasNoElement(only.whenFalse)) {
193337
+ return only;
193338
+ }
193339
+ return null;
193340
+ }
193341
+ function extractItemConditionalKey(cond) {
193342
+ const a = branchHasNoElement(cond.whenTrue) ? null : extractLoopKey(cond.whenTrue);
193343
+ const b = branchHasNoElement(cond.whenFalse) ? null : extractLoopKey(cond.whenFalse);
193344
+ if (a !== null && b !== null) {
193345
+ return normalizeKeyExpr(a) === normalizeKeyExpr(b) ? a : null;
193346
+ }
193347
+ return a ?? b;
193348
+ }
193259
193349
  function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
193260
193350
  const isNested = ctx.loopParams.size > 0;
193261
193351
  const propAccess = node.expression;
@@ -193418,6 +193508,19 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
193418
193508
  }
193419
193509
  if (index)
193420
193510
  ctx.loopParams.add(index);
193511
+ const tryTransformRenderableBody = (expr) => {
193512
+ if (!import_typescript11.default.isBinaryExpression(expr))
193513
+ return;
193514
+ const op = expr.operatorToken.kind;
193515
+ if (op !== import_typescript11.default.SyntaxKind.AmpersandAmpersandToken && op !== import_typescript11.default.SyntaxKind.BarBarToken && op !== import_typescript11.default.SyntaxKind.QuestionQuestionToken) {
193516
+ return;
193517
+ }
193518
+ if (!containsJsxInExpression(expr) && !callsJsxHelper(expr, ctx))
193519
+ return;
193520
+ const transformed = transformJsxExpression(expr, ctx, isClientOnly);
193521
+ if (transformed)
193522
+ children = [transformed];
193523
+ };
193421
193524
  const body = callback.body;
193422
193525
  if (import_typescript11.default.isJsxElement(body) || import_typescript11.default.isJsxSelfClosingElement(body) || import_typescript11.default.isJsxFragment(body)) {
193423
193526
  const transformed = transformNode(body, ctx);
@@ -193440,6 +193543,8 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
193440
193543
  children = [transformConditional(inner, ctx)];
193441
193544
  } else if (method === "flatMap" && import_typescript11.default.isArrayLiteralExpression(inner)) {
193442
193545
  children = transformArrayLiteralChildren(inner, ctx);
193546
+ } else {
193547
+ tryTransformRenderableBody(inner);
193443
193548
  }
193444
193549
  } else if (method === "flatMap" && import_typescript11.default.isArrayLiteralExpression(body)) {
193445
193550
  children = transformArrayLiteralChildren(body, ctx);
@@ -193488,6 +193593,8 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
193488
193593
  if (method === "flatMap" && children.length === 0) {
193489
193594
  flatMapCallback = buildFlatMapCallback(callback, body, ctx);
193490
193595
  }
193596
+ } else {
193597
+ tryTransformRenderableBody(body);
193491
193598
  }
193492
193599
  if (paramBindings) {
193493
193600
  for (const b of paramBindings)
@@ -193504,7 +193611,9 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
193504
193611
  if (import_typescript11.default.isArrowFunction(node.arguments[0]) && children.length > 0) {
193505
193612
  checkLoopKey(node.arguments[0], ctx, isNested);
193506
193613
  }
193507
- const key = children.length > 0 ? extractLoopKey(children[0]) : null;
193614
+ const itemConditional = children.length > 0 ? loopBodyItemConditional(children) : null;
193615
+ const bodyIsItemConditional = itemConditional !== null;
193616
+ const key = bodyIsItemConditional ? extractItemConditionalKey(itemConditional) : children.length > 0 ? extractLoopKey(children[0]) : null;
193508
193617
  let childComponent;
193509
193618
  if (children.length === 1 && children[0].type === "component") {
193510
193619
  const comp = children[0];
@@ -193543,6 +193652,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
193543
193652
  callsReactiveGetters: callsReactive || undefined,
193544
193653
  hasFunctionCalls: hasCalls || undefined,
193545
193654
  bodyIsMultiRoot: bodyIsMultiRoot || undefined,
193655
+ bodyIsItemConditional: bodyIsItemConditional || undefined,
193546
193656
  childComponent,
193547
193657
  nestedComponents,
193548
193658
  filterPredicate,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/test",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Test utilities for BarefootJS - IR-based component testing without a browser",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -39,7 +39,7 @@
39
39
  "directory": "packages/test"
40
40
  },
41
41
  "dependencies": {
42
- "@barefootjs/jsx": "0.5.0"
42
+ "@barefootjs/jsx": "0.5.2"
43
43
  },
44
44
  "devDependencies": {
45
45
  "typescript": "^5.0.0"