Also require setSpecProperty/setSuiteProperty args to be JSON serializable

This commit is contained in:
Steve Gravrock
2025-09-27 15:40:19 -07:00
parent c2ce55580c
commit e11f320df3
5 changed files with 42 additions and 12 deletions

View File

@@ -761,9 +761,12 @@ getJasmineRequireObj().util = function(j$) {
}
};
util.assertStructuredCloneable = function(v, msgPrefix) {
util.assertReporterCloneable = function(v, msgPrefix) {
try {
structuredClone(v);
// Reporter events are cloned internally via structuredClone, and it's
// common for reporters (including jasmine-browser-runner's) to JSON
// serialize them.
JSON.stringify(structuredClone(v));
} catch (e) {
throw new Error(`${msgPrefix} can't be cloned`, { cause: e });
}
@@ -848,8 +851,8 @@ getJasmineRequireObj().Spec = function(j$) {
// Key and value will eventually be cloned during reporting. The error
// thrown at that point if they aren't cloneable isn't very helpful.
// Throw a better one now.
j$.private.util.assertStructuredCloneable(key, 'Key');
j$.private.util.assertStructuredCloneable(value, 'Value');
j$.private.util.assertReporterCloneable(key, 'Key');
j$.private.util.assertReporterCloneable(value, 'Value');
this.result.properties = this.result.properties || {};
this.result.properties[key] = value;
}
@@ -10631,8 +10634,8 @@ getJasmineRequireObj().Suite = function(j$) {
// Key and value will eventually be cloned during reporting. The error
// thrown at that point if they aren't cloneable isn't very helpful.
// Throw a better one now.
j$.private.util.assertStructuredCloneable(key, 'Key');
j$.private.util.assertStructuredCloneable(value, 'Value');
j$.private.util.assertReporterCloneable(key, 'Key');
j$.private.util.assertReporterCloneable(value, 'Value');
this.result.properties = this.result.properties || {};
this.result.properties[key] = value;
}

View File

@@ -113,6 +113,18 @@ describe('Spec', function() {
}).toThrowError("Key can't be cloned");
});
it('throws if the key is not JSON-serializable', function() {
const spec = new privateUnderTest.Spec({
queueableFn: { fn: () => {} }
});
expect(function() {
const k = {};
k.self = k;
spec.setSpecProperty(k, '');
}).toThrowError("Key can't be cloned");
});
it('throws if the value is not structured-cloneable', function() {
const spec = new privateUnderTest.Spec({
queueableFn: { fn: () => {} }
@@ -122,6 +134,18 @@ describe('Spec', function() {
spec.setSpecProperty('k', new Promise(() => {}));
}).toThrowError("Value can't be cloned");
});
it('throws if the value is not JSON-serializable', function() {
const spec = new privateUnderTest.Spec({
queueableFn: { fn: () => {} }
});
expect(function() {
const v = {};
v.self = v;
spec.setSpecProperty('k', v);
}).toThrowError("Value can't be cloned");
});
});
describe('status', function() {

View File

@@ -74,8 +74,8 @@ getJasmineRequireObj().Spec = function(j$) {
// Key and value will eventually be cloned during reporting. The error
// thrown at that point if they aren't cloneable isn't very helpful.
// Throw a better one now.
j$.private.util.assertStructuredCloneable(key, 'Key');
j$.private.util.assertStructuredCloneable(value, 'Value');
j$.private.util.assertReporterCloneable(key, 'Key');
j$.private.util.assertReporterCloneable(value, 'Value');
this.result.properties = this.result.properties || {};
this.result.properties[key] = value;
}

View File

@@ -34,8 +34,8 @@ getJasmineRequireObj().Suite = function(j$) {
// Key and value will eventually be cloned during reporting. The error
// thrown at that point if they aren't cloneable isn't very helpful.
// Throw a better one now.
j$.private.util.assertStructuredCloneable(key, 'Key');
j$.private.util.assertStructuredCloneable(value, 'Value');
j$.private.util.assertReporterCloneable(key, 'Key');
j$.private.util.assertReporterCloneable(value, 'Value');
this.result.properties = this.result.properties || {};
this.result.properties[key] = value;
}

View File

@@ -80,9 +80,12 @@ getJasmineRequireObj().util = function(j$) {
}
};
util.assertStructuredCloneable = function(v, msgPrefix) {
util.assertReporterCloneable = function(v, msgPrefix) {
try {
structuredClone(v);
// Reporter events are cloned internally via structuredClone, and it's
// common for reporters (including jasmine-browser-runner's) to JSON
// serialize them.
JSON.stringify(structuredClone(v));
} catch (e) {
throw new Error(`${msgPrefix} can't be cloned`, { cause: e });
}