Skip to content

Commit

Permalink
[Tests] increase coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
ljharb committed Dec 18, 2023
1 parent 0b2b950 commit 26547ae
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 3 deletions.
4 changes: 2 additions & 2 deletions implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ module.exports = function isSupersetOf(other) {
var nextValue = IteratorValue(next); // step 8.b.i
// if (!SetDataHas(O.[[SetData]], nextValue)) { // step 8.b.ii
if (!$setHas(O, nextValue)) {
IteratorClose(keysIter, NormalCompletion());
return false;
IteratorClose(keysIter, NormalCompletion()); // step 8.b.ii.1
return false; // step 8.b.ii.2
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,14 @@
"@ljharb/eslint-config": "^21.1.0",
"aud": "^2.0.4",
"auto-changelog": "^2.4.0",
"es-map": "^1.0.5",
"es-value-fixtures": "^1.4.2",
"es6-shim": "^0.35.8",
"eslint": "=8.8.0",
"evalmd": "^0.0.19",
"for-each": "^0.3.3",
"functions-have-names": "^1.2.3",
"gopd": "^1.0.1",
"has-strict-mode": "^1.0.1",
"in-publish": "^2.0.1",
"npmignore": "^0.3.1",
Expand Down
14 changes: 14 additions & 0 deletions test/builtin.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var callBind = require('call-bind');
var isEnumerable = Object.prototype.propertyIsEnumerable;
var fnNamesConfigurable = require('functions-have-names').functionsHaveConfigurableNames();
var hasStrictMode = require('has-strict-mode')();
var gOPD = require('gopd');

var runTests = require('./tests');

Expand All @@ -24,6 +25,19 @@ module.exports = function (t) {
et.end();
});

t.test('descriptor', { skip: !defineProperties.supportsDescriptors }, function (dt) {
dt.deepEqual(
gOPD(Set.prototype, name),
{
configurable: true,
enumerable: false,
value: method,
writable: true
}
);
dt.end();
});

t.test('bad object value', { skip: !hasStrictMode }, function (st) {
/* eslint no-useless-call: 0 */
st['throws'](function () { return method.call(undefined); }, TypeError, 'undefined is not an object');
Expand Down
219 changes: 218 additions & 1 deletion test/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ var $Set = require('es-set/polyfill')();
var forEach = require('for-each');
var v = require('es-value-fixtures');
var debug = require('object-inspect');
var $Map = require('es-map/polyfill')();

module.exports = function (isSupersetOf, t) {
t.test('throws on non-set receivers', function (st) {
forEach(v.primitives.concat(v.objects), function (nonSet) {
forEach(v.primitives.concat(v.objects, [], new $Map()), function (nonSet) {
st['throws'](
function () { isSupersetOf(nonSet, {}); },
TypeError,
Expand Down Expand Up @@ -110,5 +111,221 @@ module.exports = function (isSupersetOf, t) {
st.end();
});

t.test('test262: test/built-ins/Set/prototype/isSupersetOf/allows-set-like-object', function (st) {
var s1 = new $Set([1, 2]);
var s2 = {
size: 1,
has: function () {
throw new EvalError('Set.prototype.isSupersetOf should not call its argument’s has method');
},
keys: function () {
var result = {
done: false,
value: 1
};
return {
next: function () {
try {
return result;
} finally {
result = {
done: true
};
}
}
};
}
};

st.equal(isSupersetOf(s1, s2), true);

st.end();
});

t.test('test262: test/built-ins/Set/prototype/isSupersetOf/compares-Map', function (st) {
var s1 = new $Set([1, 2]);
var m1 = new $Map([
[2, 'two'],
[3, 'three']
]);

st.equal(isSupersetOf(s1, m1), false);

st.end();
});

t.test('test262: test/built-ins/Set/prototype/isSupersetOf/compares-empty-sets', function (st) {
var s1 = new $Set([]);
var s2 = new $Set([1, 2]);

st.equal(isSupersetOf(s1, s2), false);

var s3 = new $Set([1, 2]);
var s4 = new $Set([]);

st.equal(isSupersetOf(s3, s4), true);

var s5 = new $Set([]);
var s6 = new $Set([]);

st.equal(isSupersetOf(s5, s6), true);

st.end();
});

t.test('test262: test/built-ins/Set/prototype/isSupersetOf/compares-itself', function (st) {
var s1 = new $Set([1, 2]);

st.equal(isSupersetOf(s1, s1), true);

st.end();
});

t.test('test262: test/built-ins/Set/prototype/isSupersetOf/compares-same-sets', function (st) {
var s1 = new $Set([1, 2]);
var s2 = new $Set([1, 2]);

st.equal(isSupersetOf(s1, s2), true);

st.end();
});

t.test('test262: test/built-ins/Set/prototype/isSupersetOf/has-is-callable', function (st) {
var s1 = new $Set([1, 2]);
var s2 = {
size: 2,
has: undefined,
keys: function () {
return [2, 3];
}
};
st['throws'](
function () { isSupersetOf(s1, s2); },
TypeError,
'GetSetRecord throws an error when has is undefined'
);

s2.has = {};
st['throws'](
function () { isSupersetOf(s1, s2); },
TypeError,
'GetSetRecord throws an error when has is not callable'
);

st.end();
});

t.test('test262: test/built-ins/Set/prototype/isSupersetOf/keys-is-callable', function (st) {
var s1 = new $Set([1, 2]);
var s2 = {
size: 2,
has: function () {},
keys: undefined
};
st['throws'](
function () { isSupersetOf(s1, s2); },
TypeError,
'GetSetRecord throws an error when keys is undefined'
);

s2.keys = {};
st['throws'](
function () { isSupersetOf(s1, s2); },
TypeError,
'GetSetRecord throws an error when keys is not callable'
);

st.end();
});

t.test('test262: test/built-ins/Set/prototype/isSupersetOf/set-like-array', function (st) {
var s1 = new $Set([1, 2]);
var s2 = [5, 6];
s2.size = 3;
s2.has = function (x) {
if (x === 1) { return true; }
if (x === 2) { return true; }
throw new EvalError('Set.prototype.isSupersetOf should only call its argument’s has method with contents of this');
};
s2.keys = function () {
throw new EvalError('Set.prototype.isSupersetOf should not call its argument’s keys iterator when this.size ≤ arg.size');
};

st.equal(isSupersetOf(s1, s2), false);

st.end();
});

t.test('test262: test/built-ins/Set/prototype/isSupersetOf/set-like-class-mutation', function (st) {
var baseSet = new $Set(['a', 'b', 'c']);

var evilSetLike = {
size: 3,
has: function () {
throw new EvalError('Set.prototype.isSupersetOf should not call its argument”s has method');
},
keys: function () {
var steps = [
function () { return { done: false, value: 'a' }; },
function () {
baseSet['delete']('b');
baseSet['delete']('c');
baseSet.add('b');
return { done: false, value: 'b' };
}
];
return {
next: function () {
return steps.length > 0 ? steps.shift()() : { done: true };
}
};
}
};

var result = isSupersetOf(baseSet, evilSetLike);
st.equal(result, true);

var expectedNewBase = new $Set(['a', 'b']);
st.deepEqual(baseSet, expectedNewBase, 'original Set is mutated as expected');

st.end();
});

t.test('test262: test/built-ins/Set/prototype/isSupersetOf/size-is-a-number', function (st) {
var s1 = new $Set([1, 2]);
var s2 = {
size: undefined,
has: function () {},
keys: function () {
return [2, 3];
}
};

forEach([undefined, NaN, 'string'].concat(v.bigints), function (size) {
s2.size = size;
st['throws'](
function () { isSupersetOf(s1, s2); },
TypeError,
'GetSetRecord throws an error when size is ' + debug(size)
);
});

var coercionCalls = 0;
s2.size = {
valueOf: function () {
coercionCalls += 1;
return NaN;
}
};
st['throws'](
function () { isSupersetOf(s1, s2); },
TypeError,
'GetSetRecord throws an error when size coerces to NaN'
);
st.equal(coercionCalls, 1, 'GetSetRecord coerces size');

st.end();
});

return t.comment('tests completed');
};

0 comments on commit 26547ae

Please sign in to comment.