@postman-cse/onboarding-bootstrap 2.9.8 → 2.9.9

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/action.cjs CHANGED
@@ -261017,6 +261017,13 @@ function normalizeResponseKey(status) {
261017
261017
  const raw = String(status);
261018
261018
  return /^[1-5]xx$/i.test(raw) ? raw.toUpperCase() : raw;
261019
261019
  }
261020
+ function responseBodyExpectation(method, status, content) {
261021
+ const normalizedStatus = normalizeResponseKey(status);
261022
+ if (method === "head" || normalizedStatus === "1XX" || /^1[0-9][0-9]$/.test(normalizedStatus) || normalizedStatus === "204" || normalizedStatus === "205" || normalizedStatus === "304") {
261023
+ return "forbidden";
261024
+ }
261025
+ return Object.keys(content).length > 0 ? "declared" : "unknown";
261026
+ }
261020
261027
  function collectSecurityApiKeys(root, operation) {
261021
261028
  const securitySchemes = asRecord5(asRecord5(root.components)?.securitySchemes);
261022
261029
  const requirements = operation.security === void 0 ? asArray2(root.security) : asArray2(operation.security);
@@ -261447,6 +261454,13 @@ function collectRequestBody(root, operation, version, operationId, warnings) {
261447
261454
  const body2 = resolveInternalRef(root, operation.requestBody);
261448
261455
  if (!body2) return void 0;
261449
261456
  const content = asRecord5(body2.content);
261457
+ for (const [contentType2, mediaObject] of Object.entries(content ?? {})) {
261458
+ if (asRecord5(mediaObject)?.schema === void 0) {
261459
+ warnings.push(
261460
+ `CONTRACT_REQUEST_SCHEMA_UNDOCUMENTED: request body ${contentType2} on ${operationId} declares no schema; generated request payload shape is not validated`
261461
+ );
261462
+ }
261463
+ }
261450
261464
  const fieldRules = content ? requestBodyFieldRules(root, content, version, operationId, warnings) : void 0;
261451
261465
  if (fieldRules) {
261452
261466
  for (const [base, rule] of Object.entries(fieldRules)) {
@@ -262293,9 +262307,22 @@ function buildContractIndex(root) {
262293
262307
  const linkExpressions = collectLinkExpressions(root, response, `${lowerMethod.toUpperCase()} ${path10}`, responseWarnings, version, linkTargetSchemas);
262294
262308
  const responseContext = `${lowerMethod.toUpperCase()} ${path10} status ${status}`;
262295
262309
  const content = responseContent(root, version, response, responseContext, responseWarnings);
262296
- if ((status === "204" || status === "205" || status === "304") && Object.keys(content).length > 0) {
262310
+ const bodyExpectation = responseBodyExpectation(lowerMethod, status, content);
262311
+ if (bodyExpectation === "forbidden" && Object.keys(content).length > 0) {
262297
262312
  responseWarnings.add(`CONTRACT_BODYLESS_STATUS_WITH_CONTENT: ${lowerMethod.toUpperCase()} ${path10} declares content for status ${status}, which RFC 9110 forbids on the wire`);
262298
262313
  }
262314
+ if (bodyExpectation === "unknown") {
262315
+ responseWarnings.add(
262316
+ `CONTRACT_RESPONSE_BODY_UNDOCUMENTED: ${responseContext} declares no response content; body presence, media type, and shape are not validated`
262317
+ );
262318
+ }
262319
+ for (const [contentType2, mediaObject] of Object.entries(asRecord5(response.content) ?? {})) {
262320
+ if (asRecord5(mediaObject)?.schema === void 0) {
262321
+ responseWarnings.add(
262322
+ `CONTRACT_RESPONSE_SCHEMA_UNDOCUMENTED: response ${contentType2} on ${responseContext} declares no schema; body shape is not validated`
262323
+ );
262324
+ }
262325
+ }
262299
262326
  for (const [contentType2, media] of Object.entries(content)) {
262300
262327
  const base = contentType2.toLowerCase().split(";")[0]?.trim() ?? "";
262301
262328
  const schemaType = asRecord5(media.schema)?.type;
@@ -262307,7 +262334,7 @@ function buildContractIndex(root) {
262307
262334
  const writeOnlyProperties = collectResponseWriteOnlyNames(root, response);
262308
262335
  contractResponses[normalizeResponseKey(status)] = {
262309
262336
  content,
262310
- hasBody: Object.keys(content).length > 0,
262337
+ bodyExpectation,
262311
262338
  headers,
262312
262339
  ...linkExpressions.length > 0 ? { links: linkExpressions } : {},
262313
262340
  ...writeOnlyProperties.length > 0 ? { writeOnlyProperties } : {}
@@ -262583,7 +262610,12 @@ function createContractScript(operation, warnings = []) {
262583
262610
  " return null;",
262584
262611
  "}",
262585
262612
  'function responseText() { return pm.response.text() || ""; }',
262586
- 'function isBodyless() { return pm.response.code === 204 || pm.response.code === 205 || pm.response.code === 304 || contract.method === "HEAD"; }',
262613
+ 'function isBodyless() { return pm.response.code < 200 || pm.response.code === 204 || pm.response.code === 205 || pm.response.code === 304 || contract.method === "HEAD"; }',
262614
+ "function selectedBodyExpectation() {",
262615
+ ' if (isBodyless()) return "forbidden";',
262616
+ ' if (!selected) return "unknown";',
262617
+ ' return selected.value.bodyExpectation || "unknown";',
262618
+ "}",
262587
262619
  'function mediaBase(value) { return String(value || "").toLowerCase().split(";")[0].trim(); }',
262588
262620
  'function mediaParts(value) { var base = mediaBase(value); var parts = base.split("/"); return { raw: base, type: parts[0] || "", subtype: parts[1] || "" }; }',
262589
262621
  'function isJsonSubtype(subtype) { return subtype === "json" || /\\+json$/.test(subtype); }',
@@ -262623,6 +262655,7 @@ function createContractScript(operation, warnings = []) {
262623
262655
  " return matches[0];",
262624
262656
  "}",
262625
262657
  "var selected = selectedResponseContract();",
262658
+ "var bodyExpectation = selectedBodyExpectation();",
262626
262659
  ...skipped.length > 0 ? [
262627
262660
  // A schema schemasafe could not compile is NOT silently ignored: it is
262628
262661
  // surfaced here (and as a CONTRACT_SCHEMA_NOT_COMPILED warning at generation
@@ -262654,10 +262687,8 @@ function createContractScript(operation, warnings = []) {
262654
262687
  "});",
262655
262688
  "pm.test('Response body matches OpenAPI body contract', function () {",
262656
262689
  " if (!selected) return;",
262657
- " if (isBodyless()) { pm.expect(responseText().trim().length).to.equal(0); return; }",
262658
- " var content = selected.value.content || {};",
262659
- ' if (Object.keys(content).length === 0) { pm.expect(responseText().trim().length, "OpenAPI response defines no body but response body was not empty").to.equal(0); }',
262660
- ' else { pm.expect(responseText().trim().length, "OpenAPI response defines a body but response body was empty").to.be.above(0); }',
262690
+ ' if (bodyExpectation === "forbidden") { pm.expect(responseText().length, "HTTP semantics forbid a response body for " + contract.method + " " + contract.path + " status " + pm.response.code).to.equal(0); return; }',
262691
+ ' if (bodyExpectation === "declared") { pm.expect(responseText().length, "OpenAPI response declares content but response body was empty").to.be.above(0); }',
262661
262692
  "});",
262662
262693
  "pm.test('Content-Type matches OpenAPI response content', function () {",
262663
262694
  " if (!selected || isBodyless()) return;",
@@ -263700,8 +263731,7 @@ function createContractScript(operation, warnings = []) {
263700
263731
  ' if (contract.method === "HEAD" || pm.response.code === 304) return;',
263701
263732
  " var actualBytes = unescape(encodeURIComponent(responseText())).length;",
263702
263733
  ' if (Number(String(raw).trim()) !== actualBytes) pm.expect.fail("Content-Length must equal the response body byte length when Content-Encoding and Transfer-Encoding are absent (RFC 9110 8.6): " + raw + " !== " + actualBytes);',
263703
- " var mustBeEmpty = isBodyless() || (selected && Object.keys(selected.value.content || {}).length === 0);",
263704
- ' if (mustBeEmpty && Number(String(raw).trim()) !== 0) pm.expect.fail("OpenAPI defines no response body for " + contract.method + " " + contract.path + " status " + pm.response.code + " but Content-Length was " + raw);',
263734
+ ' if (bodyExpectation === "forbidden" && Number(String(raw).trim()) !== 0) pm.expect.fail("HTTP semantics forbid a carried response body for " + contract.method + " " + contract.path + " status " + pm.response.code + " but Content-Length was " + raw);',
263705
263735
  "});",
263706
263736
  "pm.test('RFC SHOULD-level advisories are documented', function () {",
263707
263737
  ' pm.expect(rfcAdvisories, "SHOULD-level findings (advisory, non-failing): " + rfcAdvisories.join("; ")).to.be.an("array");',
package/dist/cli.cjs CHANGED
@@ -259335,6 +259335,13 @@ function normalizeResponseKey(status) {
259335
259335
  const raw = String(status);
259336
259336
  return /^[1-5]xx$/i.test(raw) ? raw.toUpperCase() : raw;
259337
259337
  }
259338
+ function responseBodyExpectation(method, status, content) {
259339
+ const normalizedStatus = normalizeResponseKey(status);
259340
+ if (method === "head" || normalizedStatus === "1XX" || /^1[0-9][0-9]$/.test(normalizedStatus) || normalizedStatus === "204" || normalizedStatus === "205" || normalizedStatus === "304") {
259341
+ return "forbidden";
259342
+ }
259343
+ return Object.keys(content).length > 0 ? "declared" : "unknown";
259344
+ }
259338
259345
  function collectSecurityApiKeys(root, operation) {
259339
259346
  const securitySchemes = asRecord5(asRecord5(root.components)?.securitySchemes);
259340
259347
  const requirements = operation.security === void 0 ? asArray2(root.security) : asArray2(operation.security);
@@ -259765,6 +259772,13 @@ function collectRequestBody(root, operation, version, operationId, warnings) {
259765
259772
  const body2 = resolveInternalRef(root, operation.requestBody);
259766
259773
  if (!body2) return void 0;
259767
259774
  const content = asRecord5(body2.content);
259775
+ for (const [contentType2, mediaObject] of Object.entries(content ?? {})) {
259776
+ if (asRecord5(mediaObject)?.schema === void 0) {
259777
+ warnings.push(
259778
+ `CONTRACT_REQUEST_SCHEMA_UNDOCUMENTED: request body ${contentType2} on ${operationId} declares no schema; generated request payload shape is not validated`
259779
+ );
259780
+ }
259781
+ }
259768
259782
  const fieldRules = content ? requestBodyFieldRules(root, content, version, operationId, warnings) : void 0;
259769
259783
  if (fieldRules) {
259770
259784
  for (const [base, rule] of Object.entries(fieldRules)) {
@@ -260611,9 +260625,22 @@ function buildContractIndex(root) {
260611
260625
  const linkExpressions = collectLinkExpressions(root, response, `${lowerMethod.toUpperCase()} ${path8}`, responseWarnings, version, linkTargetSchemas);
260612
260626
  const responseContext = `${lowerMethod.toUpperCase()} ${path8} status ${status}`;
260613
260627
  const content = responseContent(root, version, response, responseContext, responseWarnings);
260614
- if ((status === "204" || status === "205" || status === "304") && Object.keys(content).length > 0) {
260628
+ const bodyExpectation = responseBodyExpectation(lowerMethod, status, content);
260629
+ if (bodyExpectation === "forbidden" && Object.keys(content).length > 0) {
260615
260630
  responseWarnings.add(`CONTRACT_BODYLESS_STATUS_WITH_CONTENT: ${lowerMethod.toUpperCase()} ${path8} declares content for status ${status}, which RFC 9110 forbids on the wire`);
260616
260631
  }
260632
+ if (bodyExpectation === "unknown") {
260633
+ responseWarnings.add(
260634
+ `CONTRACT_RESPONSE_BODY_UNDOCUMENTED: ${responseContext} declares no response content; body presence, media type, and shape are not validated`
260635
+ );
260636
+ }
260637
+ for (const [contentType2, mediaObject] of Object.entries(asRecord5(response.content) ?? {})) {
260638
+ if (asRecord5(mediaObject)?.schema === void 0) {
260639
+ responseWarnings.add(
260640
+ `CONTRACT_RESPONSE_SCHEMA_UNDOCUMENTED: response ${contentType2} on ${responseContext} declares no schema; body shape is not validated`
260641
+ );
260642
+ }
260643
+ }
260617
260644
  for (const [contentType2, media] of Object.entries(content)) {
260618
260645
  const base = contentType2.toLowerCase().split(";")[0]?.trim() ?? "";
260619
260646
  const schemaType = asRecord5(media.schema)?.type;
@@ -260625,7 +260652,7 @@ function buildContractIndex(root) {
260625
260652
  const writeOnlyProperties = collectResponseWriteOnlyNames(root, response);
260626
260653
  contractResponses[normalizeResponseKey(status)] = {
260627
260654
  content,
260628
- hasBody: Object.keys(content).length > 0,
260655
+ bodyExpectation,
260629
260656
  headers,
260630
260657
  ...linkExpressions.length > 0 ? { links: linkExpressions } : {},
260631
260658
  ...writeOnlyProperties.length > 0 ? { writeOnlyProperties } : {}
@@ -260901,7 +260928,12 @@ function createContractScript(operation, warnings = []) {
260901
260928
  " return null;",
260902
260929
  "}",
260903
260930
  'function responseText() { return pm.response.text() || ""; }',
260904
- 'function isBodyless() { return pm.response.code === 204 || pm.response.code === 205 || pm.response.code === 304 || contract.method === "HEAD"; }',
260931
+ 'function isBodyless() { return pm.response.code < 200 || pm.response.code === 204 || pm.response.code === 205 || pm.response.code === 304 || contract.method === "HEAD"; }',
260932
+ "function selectedBodyExpectation() {",
260933
+ ' if (isBodyless()) return "forbidden";',
260934
+ ' if (!selected) return "unknown";',
260935
+ ' return selected.value.bodyExpectation || "unknown";',
260936
+ "}",
260905
260937
  'function mediaBase(value) { return String(value || "").toLowerCase().split(";")[0].trim(); }',
260906
260938
  'function mediaParts(value) { var base = mediaBase(value); var parts = base.split("/"); return { raw: base, type: parts[0] || "", subtype: parts[1] || "" }; }',
260907
260939
  'function isJsonSubtype(subtype) { return subtype === "json" || /\\+json$/.test(subtype); }',
@@ -260941,6 +260973,7 @@ function createContractScript(operation, warnings = []) {
260941
260973
  " return matches[0];",
260942
260974
  "}",
260943
260975
  "var selected = selectedResponseContract();",
260976
+ "var bodyExpectation = selectedBodyExpectation();",
260944
260977
  ...skipped.length > 0 ? [
260945
260978
  // A schema schemasafe could not compile is NOT silently ignored: it is
260946
260979
  // surfaced here (and as a CONTRACT_SCHEMA_NOT_COMPILED warning at generation
@@ -260972,10 +261005,8 @@ function createContractScript(operation, warnings = []) {
260972
261005
  "});",
260973
261006
  "pm.test('Response body matches OpenAPI body contract', function () {",
260974
261007
  " if (!selected) return;",
260975
- " if (isBodyless()) { pm.expect(responseText().trim().length).to.equal(0); return; }",
260976
- " var content = selected.value.content || {};",
260977
- ' if (Object.keys(content).length === 0) { pm.expect(responseText().trim().length, "OpenAPI response defines no body but response body was not empty").to.equal(0); }',
260978
- ' else { pm.expect(responseText().trim().length, "OpenAPI response defines a body but response body was empty").to.be.above(0); }',
261008
+ ' if (bodyExpectation === "forbidden") { pm.expect(responseText().length, "HTTP semantics forbid a response body for " + contract.method + " " + contract.path + " status " + pm.response.code).to.equal(0); return; }',
261009
+ ' if (bodyExpectation === "declared") { pm.expect(responseText().length, "OpenAPI response declares content but response body was empty").to.be.above(0); }',
260979
261010
  "});",
260980
261011
  "pm.test('Content-Type matches OpenAPI response content', function () {",
260981
261012
  " if (!selected || isBodyless()) return;",
@@ -262018,8 +262049,7 @@ function createContractScript(operation, warnings = []) {
262018
262049
  ' if (contract.method === "HEAD" || pm.response.code === 304) return;',
262019
262050
  " var actualBytes = unescape(encodeURIComponent(responseText())).length;",
262020
262051
  ' if (Number(String(raw).trim()) !== actualBytes) pm.expect.fail("Content-Length must equal the response body byte length when Content-Encoding and Transfer-Encoding are absent (RFC 9110 8.6): " + raw + " !== " + actualBytes);',
262021
- " var mustBeEmpty = isBodyless() || (selected && Object.keys(selected.value.content || {}).length === 0);",
262022
- ' if (mustBeEmpty && Number(String(raw).trim()) !== 0) pm.expect.fail("OpenAPI defines no response body for " + contract.method + " " + contract.path + " status " + pm.response.code + " but Content-Length was " + raw);',
262052
+ ' if (bodyExpectation === "forbidden" && Number(String(raw).trim()) !== 0) pm.expect.fail("HTTP semantics forbid a carried response body for " + contract.method + " " + contract.path + " status " + pm.response.code + " but Content-Length was " + raw);',
262023
262053
  "});",
262024
262054
  "pm.test('RFC SHOULD-level advisories are documented', function () {",
262025
262055
  ' pm.expect(rfcAdvisories, "SHOULD-level findings (advisory, non-failing): " + rfcAdvisories.join("; ")).to.be.an("array");',
package/dist/index.cjs CHANGED
@@ -261042,6 +261042,13 @@ function normalizeResponseKey(status) {
261042
261042
  const raw = String(status);
261043
261043
  return /^[1-5]xx$/i.test(raw) ? raw.toUpperCase() : raw;
261044
261044
  }
261045
+ function responseBodyExpectation(method, status, content) {
261046
+ const normalizedStatus = normalizeResponseKey(status);
261047
+ if (method === "head" || normalizedStatus === "1XX" || /^1[0-9][0-9]$/.test(normalizedStatus) || normalizedStatus === "204" || normalizedStatus === "205" || normalizedStatus === "304") {
261048
+ return "forbidden";
261049
+ }
261050
+ return Object.keys(content).length > 0 ? "declared" : "unknown";
261051
+ }
261045
261052
  function collectSecurityApiKeys(root, operation) {
261046
261053
  const securitySchemes = asRecord5(asRecord5(root.components)?.securitySchemes);
261047
261054
  const requirements = operation.security === void 0 ? asArray2(root.security) : asArray2(operation.security);
@@ -261472,6 +261479,13 @@ function collectRequestBody(root, operation, version, operationId, warnings) {
261472
261479
  const body2 = resolveInternalRef(root, operation.requestBody);
261473
261480
  if (!body2) return void 0;
261474
261481
  const content = asRecord5(body2.content);
261482
+ for (const [contentType2, mediaObject] of Object.entries(content ?? {})) {
261483
+ if (asRecord5(mediaObject)?.schema === void 0) {
261484
+ warnings.push(
261485
+ `CONTRACT_REQUEST_SCHEMA_UNDOCUMENTED: request body ${contentType2} on ${operationId} declares no schema; generated request payload shape is not validated`
261486
+ );
261487
+ }
261488
+ }
261475
261489
  const fieldRules = content ? requestBodyFieldRules(root, content, version, operationId, warnings) : void 0;
261476
261490
  if (fieldRules) {
261477
261491
  for (const [base, rule] of Object.entries(fieldRules)) {
@@ -262318,9 +262332,22 @@ function buildContractIndex(root) {
262318
262332
  const linkExpressions = collectLinkExpressions(root, response, `${lowerMethod.toUpperCase()} ${path10}`, responseWarnings, version, linkTargetSchemas);
262319
262333
  const responseContext = `${lowerMethod.toUpperCase()} ${path10} status ${status}`;
262320
262334
  const content = responseContent(root, version, response, responseContext, responseWarnings);
262321
- if ((status === "204" || status === "205" || status === "304") && Object.keys(content).length > 0) {
262335
+ const bodyExpectation = responseBodyExpectation(lowerMethod, status, content);
262336
+ if (bodyExpectation === "forbidden" && Object.keys(content).length > 0) {
262322
262337
  responseWarnings.add(`CONTRACT_BODYLESS_STATUS_WITH_CONTENT: ${lowerMethod.toUpperCase()} ${path10} declares content for status ${status}, which RFC 9110 forbids on the wire`);
262323
262338
  }
262339
+ if (bodyExpectation === "unknown") {
262340
+ responseWarnings.add(
262341
+ `CONTRACT_RESPONSE_BODY_UNDOCUMENTED: ${responseContext} declares no response content; body presence, media type, and shape are not validated`
262342
+ );
262343
+ }
262344
+ for (const [contentType2, mediaObject] of Object.entries(asRecord5(response.content) ?? {})) {
262345
+ if (asRecord5(mediaObject)?.schema === void 0) {
262346
+ responseWarnings.add(
262347
+ `CONTRACT_RESPONSE_SCHEMA_UNDOCUMENTED: response ${contentType2} on ${responseContext} declares no schema; body shape is not validated`
262348
+ );
262349
+ }
262350
+ }
262324
262351
  for (const [contentType2, media] of Object.entries(content)) {
262325
262352
  const base = contentType2.toLowerCase().split(";")[0]?.trim() ?? "";
262326
262353
  const schemaType = asRecord5(media.schema)?.type;
@@ -262332,7 +262359,7 @@ function buildContractIndex(root) {
262332
262359
  const writeOnlyProperties = collectResponseWriteOnlyNames(root, response);
262333
262360
  contractResponses[normalizeResponseKey(status)] = {
262334
262361
  content,
262335
- hasBody: Object.keys(content).length > 0,
262362
+ bodyExpectation,
262336
262363
  headers,
262337
262364
  ...linkExpressions.length > 0 ? { links: linkExpressions } : {},
262338
262365
  ...writeOnlyProperties.length > 0 ? { writeOnlyProperties } : {}
@@ -262608,7 +262635,12 @@ function createContractScript(operation, warnings = []) {
262608
262635
  " return null;",
262609
262636
  "}",
262610
262637
  'function responseText() { return pm.response.text() || ""; }',
262611
- 'function isBodyless() { return pm.response.code === 204 || pm.response.code === 205 || pm.response.code === 304 || contract.method === "HEAD"; }',
262638
+ 'function isBodyless() { return pm.response.code < 200 || pm.response.code === 204 || pm.response.code === 205 || pm.response.code === 304 || contract.method === "HEAD"; }',
262639
+ "function selectedBodyExpectation() {",
262640
+ ' if (isBodyless()) return "forbidden";',
262641
+ ' if (!selected) return "unknown";',
262642
+ ' return selected.value.bodyExpectation || "unknown";',
262643
+ "}",
262612
262644
  'function mediaBase(value) { return String(value || "").toLowerCase().split(";")[0].trim(); }',
262613
262645
  'function mediaParts(value) { var base = mediaBase(value); var parts = base.split("/"); return { raw: base, type: parts[0] || "", subtype: parts[1] || "" }; }',
262614
262646
  'function isJsonSubtype(subtype) { return subtype === "json" || /\\+json$/.test(subtype); }',
@@ -262648,6 +262680,7 @@ function createContractScript(operation, warnings = []) {
262648
262680
  " return matches[0];",
262649
262681
  "}",
262650
262682
  "var selected = selectedResponseContract();",
262683
+ "var bodyExpectation = selectedBodyExpectation();",
262651
262684
  ...skipped.length > 0 ? [
262652
262685
  // A schema schemasafe could not compile is NOT silently ignored: it is
262653
262686
  // surfaced here (and as a CONTRACT_SCHEMA_NOT_COMPILED warning at generation
@@ -262679,10 +262712,8 @@ function createContractScript(operation, warnings = []) {
262679
262712
  "});",
262680
262713
  "pm.test('Response body matches OpenAPI body contract', function () {",
262681
262714
  " if (!selected) return;",
262682
- " if (isBodyless()) { pm.expect(responseText().trim().length).to.equal(0); return; }",
262683
- " var content = selected.value.content || {};",
262684
- ' if (Object.keys(content).length === 0) { pm.expect(responseText().trim().length, "OpenAPI response defines no body but response body was not empty").to.equal(0); }',
262685
- ' else { pm.expect(responseText().trim().length, "OpenAPI response defines a body but response body was empty").to.be.above(0); }',
262715
+ ' if (bodyExpectation === "forbidden") { pm.expect(responseText().length, "HTTP semantics forbid a response body for " + contract.method + " " + contract.path + " status " + pm.response.code).to.equal(0); return; }',
262716
+ ' if (bodyExpectation === "declared") { pm.expect(responseText().length, "OpenAPI response declares content but response body was empty").to.be.above(0); }',
262686
262717
  "});",
262687
262718
  "pm.test('Content-Type matches OpenAPI response content', function () {",
262688
262719
  " if (!selected || isBodyless()) return;",
@@ -263725,8 +263756,7 @@ function createContractScript(operation, warnings = []) {
263725
263756
  ' if (contract.method === "HEAD" || pm.response.code === 304) return;',
263726
263757
  " var actualBytes = unescape(encodeURIComponent(responseText())).length;",
263727
263758
  ' if (Number(String(raw).trim()) !== actualBytes) pm.expect.fail("Content-Length must equal the response body byte length when Content-Encoding and Transfer-Encoding are absent (RFC 9110 8.6): " + raw + " !== " + actualBytes);',
263728
- " var mustBeEmpty = isBodyless() || (selected && Object.keys(selected.value.content || {}).length === 0);",
263729
- ' if (mustBeEmpty && Number(String(raw).trim()) !== 0) pm.expect.fail("OpenAPI defines no response body for " + contract.method + " " + contract.path + " status " + pm.response.code + " but Content-Length was " + raw);',
263759
+ ' if (bodyExpectation === "forbidden" && Number(String(raw).trim()) !== 0) pm.expect.fail("HTTP semantics forbid a carried response body for " + contract.method + " " + contract.path + " status " + pm.response.code + " but Content-Length was " + raw);',
263730
263760
  "});",
263731
263761
  "pm.test('RFC SHOULD-level advisories are documented', function () {",
263732
263762
  ' pm.expect(rfcAdvisories, "SHOULD-level findings (advisory, non-failing): " + rfcAdvisories.join("; ")).to.be.an("array");',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postman-cse/onboarding-bootstrap",
3
- "version": "2.9.8",
3
+ "version": "2.9.9",
4
4
  "description": "Bootstrap Postman workspaces, specs, and collections from OpenAPI.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",