Skip to content

Commit

Permalink
.define method for temporarily defining new properties during the tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gukoff committed Aug 11, 2023
1 parent 494e437 commit 6352335
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 3 deletions.
32 changes: 29 additions & 3 deletions lib/sinon/sandbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,10 @@ function Sandbox() {
const descriptor = getPropertyDescriptor(object, property);

function restorer() {
if (descriptor.isOwn) {
if (typeof descriptor === 'undefined') {
object[property] = undefined;
}
else if (descriptor.isOwn) {
Object.defineProperty(object, property, descriptor);
} else {
delete object[property];
Expand Down Expand Up @@ -268,8 +271,6 @@ function Sandbox() {
);
}

verifyNotReplaced(object, property);

// store a function for restoring the replaced property
push(fakeRestorers, getFakeRestorer(object, property));

Expand All @@ -278,6 +279,31 @@ function Sandbox() {
return replacement;
};

sandbox.define = function define(object, property, value) {
const descriptor = getPropertyDescriptor(object, property);

if (typeof descriptor !== "undefined") {
throw new TypeError(
`Cannot define the already existing property ${valueToString(
property
)}`
);
}

if (typeof value === "undefined") {
throw new TypeError("Expected value argument to be defined");
}

verifyNotReplaced(object, property);

// store a function for restoring the defined property
push(fakeRestorers, getFakeRestorer(object, property));

object[property] = value;

return value;
};

sandbox.replaceGetter = function replaceGetter(
object,
property,
Expand Down
77 changes: 77 additions & 0 deletions test/sandbox-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,83 @@ describe("Sandbox", function () {
});
});

describe(".define", function () {
beforeEach(function () {
this.sandbox = createSandbox();
});

afterEach(function () {
this.sandbox.restore();
});

it("should define a function property", function () {
function newFunction() {
return;
}

const object = {};

this.sandbox.define(object, "property", newFunction);

assert.equals(object.property, newFunction);

this.sandbox.restore();

assert.isUndefined(object.property);
});

it("should define a non-function property", function () {
const newValue = "some-new-value";
const object = {};

this.sandbox.define(object, "property", newValue);

assert.equals(object.property, newValue);

this.sandbox.restore();

assert.isUndefined(object.property);
});

it("should error on existing descriptor", function () {
const sandbox = this.sandbox;

const existingValue = "123";
const existingFunction = () => "abcd";

const object = {
existingValue: existingValue,
existingFunction: existingFunction
};

assert.exception(
function () {
sandbox.define(object, "existingValue", "new value");
},
{
message:
"Cannot define the already existing property existingValue",
name: "TypeError",
}
);

assert.exception(
function () {
sandbox.define(object, "existingFunction", () => "new function");
},
{
message:
"Cannot define the already existing property existingFunction",
name: "TypeError",
}
);

// Verify that the methods above, even though they failed, did not replace the values
assert.equals(object.existingValue, existingValue);
assert.equals(object.existingFunction, existingFunction);
});
});

describe(".replace", function () {
beforeEach(function () {
this.sandbox = createSandbox();
Expand Down

0 comments on commit 6352335

Please sign in to comment.