1 // Copyright 2022-present 650 Industries. All rights reserved.
2 
3 import ExpoModulesTestCore
4 
5 @testable import ExpoModulesCore
6 
7 final class JavaScriptObjectSpec: ExpoSpec {
specnull8   override func spec() {
9     let runtime = JavaScriptRuntime()
10     var object: JavaScriptObject?
11 
12     let key = "expo"
13     let value1 = "��"
14     let value2 = "��"
15 
16     beforeEach {
17       object = runtime.createObject()
18     }
19 
20     describe("hasProperty") {
21       it("returns false when the property is missing") {
22         expect(object?.hasProperty(key)) == false
23       }
24 
25       it("returns true when the property exists") {
26         object?.setProperty(key, value: value1)
27         expect(object?.hasProperty(key)) == true
28       }
29 
30       it("returns true when the property is explicitly set to undefined") {
31         object?.setProperty(key, value: nil)
32         expect(object?.hasProperty(key)) == true
33         expect(object?.getProperty(key).isUndefined()) == true
34       }
35     }
36 
37     describe("getProperty") {
38       it("returns correct value") {
39         object?.setProperty(key, value: value1)
40         expect(try! object?.getProperty(key).asString()) == value1
41       }
42 
43       it("returns undefined") {
44         expect(object?.getProperty("bar").isUndefined()) == true
45       }
46     }
47 
48     describe("setProperty") {
49       it("sets") {
50         object?.setProperty(key, value: value1)
51         expect(try! object?.getProperty(key).asString()) == value1
52       }
53 
54       it("overrides") {
55         object?.setProperty(key, value: value1)
56         object?.setProperty(key, value: value2)
57         expect(try! object?.getProperty(key).asString()) == value2
58       }
59 
60       it("unsets") {
61         object?.setProperty(key, value: nil)
62         expect(object?.getProperty(key).isUndefined()) == true
63       }
64     }
65 
66     describe("defineProperty") {
67       it("defines non-enumerable property") {
68         object?.defineProperty(key, value: value1, options: [])
69         expect(try! object?.getProperty(key).asString()) == value1
70         expect(object?.getPropertyNames()).notTo(contain(key))
71       }
72 
73       it("defines enumerable property") {
74         // When the property is enumerable, it is listed in the property names
75         object?.defineProperty(key, value: value1, options: .enumerable)
76         expect(try! object?.getProperty(key).asString()) == value1
77         expect(object?.getPropertyNames()).to(contain(key))
78       }
79 
80       it("defines configurable property") {
81         // Configurable allows to redefine the property
82         object?.defineProperty(key, value: value1, options: .configurable)
83         expect(try! object?.getProperty(key).asString()) == value1
84         object?.defineProperty(key, value: value2, options: [])
85         expect(try! object?.getProperty(key).asString()) == value2
86       }
87 
88       it("defines writable property") {
89         // Writable allows changing the property
90         object?.defineProperty(key, value: value1, options: .writable)
91         expect(try! object?.getProperty(key).asString()) == value1
92         object?.setProperty(key, value: value2)
93         expect(try! object?.getProperty(key).asString()) == value2
94       }
95     }
96   }
97 }
98