Repository: unexpectedjs/unexpected
Pull request #695 (2020-02-08 23:15:01)

Remove support for: not to have (configurable|enumerable|writable) property
The semantics of `not to have configurable/... property <string>` are unclear -- should the assertion pass when the property is there, but not configurable? Should it pass when the property is absent?

I think we should just remove this variant, as we already have `not to have property <string>`

Also, fix crash when the asserted property is absent.

papandreou: I cannot reproduce the failing Chrome Headless test locally, but I think I remember seeing it before: https://travis-ci.org/unexpectedjs/unexpected/jobs/647863949#L311-L328
papandreou: The failing build seems to be an engine bug that causes unexpected to use the assertion handler `<object> to have properties <object>` in a case where it should clearly pick the more specific `<object> to have properties <array>`. The bug comes and goes in the Chrome Headless and deno builds, but I'm unable to reproduce it locally. Will try to figure it out.

Patch:
diff --git a/lib/assertions.js b/lib/assertions.js
index 1234351b..3b3d10e6 100644
--- a/lib/assertions.js
+++ b/lib/assertions.js
@@ -277,13 +277,12 @@ module.exports = expect => {
   );
 
   expect.addAssertion(
-    '<object> [not] to have (enumerable|configurable|writable) property <string>',
+    '<object> to have (enumerable|configurable|writable) property <string>',
     (expect, subject, key) => {
-      const descriptor = expect.alternations[0];
-      expect(
-        Object.getOwnPropertyDescriptor(subject, key)[descriptor],
-        '[not] to be truthy'
-      );
+      const attribute = expect.alternations[0];
+      const descriptor = Object.getOwnPropertyDescriptor(subject, key);
+      expect(descriptor, 'to be defined');
+      expect(descriptor[attribute], 'to be truthy');
       return subject[key];
     }
   );


Test patch:
diff --git a/test/assertions/to-have-property.spec.js b/test/assertions/to-have-property.spec.js
index 50d4685d..64fb6290 100644
--- a/test/assertions/to-have-property.spec.js
+++ b/test/assertions/to-have-property.spec.js
@@ -29,11 +29,8 @@ describe('to have property assertion', () => {
 
     it('asserts validity of property descriptor', () => {
       expect(subject, 'to have enumerable property', 'a');
-      expect(subject, 'not to have enumerable property', 'enumFalse');
       expect(subject, 'to have configurable property', 'a');
-      expect(subject, 'not to have configurable property', 'configFalse');
       expect(subject, 'to have writable property', 'a');
-      expect(subject, 'not to have writable property', 'writableFalse');
     });
 
     it('throws when assertion fails', () => {
@@ -62,6 +59,15 @@ describe('to have property assertion', () => {
           "to have writable property 'writableFalse'"
       );
     });
+
+    // Regression test
+    it('does not break when the object does not have the given property', function() {
+      expect(
+        () => expect({}, 'to have configurable property', 'foo'),
+        'to throw',
+        "expected {} to have configurable property 'foo'"
+      );
+    });
   });
 
   it('throws when the assertion fails', () => {