1 | /* Javascript Object Inheritance Implementation ______ ________ |
||
2 | * (c) 2016 <[email protected]> __ / / __ \/ _/ _/ |
||
3 | * Licensed under MIT. / // / /_/ // /_/ / |
||
4 | * ------------------------------------------------------ \___/\____/___/__*/ |
||
5 | var JOII = require('../../dist/joii').JOII; |
||
6 | |||
7 | /** |
||
8 | * Tests inheritance of instantiated class defintions. |
||
9 | */ |
||
10 | test('ClassBuilder:StaticTest', function(assert) { |
||
11 | |||
12 | var TestClass1 = JOII.ClassBuilder("TestClass1", {}, function (TestClass1) { return { |
||
0 ignored issues
–
show
|
|||
13 | 'private static number static_private_num' : 1, |
||
14 | 'protected static number static_protected_num' : 1, |
||
15 | 'public static number static_num' : 1, |
||
16 | 'public number instance_num' : 1, |
||
17 | 'public static function test' : function() { |
||
18 | TestClass1.static_num = 2; |
||
19 | this.instance_num = 3; // doesn't actually exist in the static scope |
||
20 | return true; |
||
21 | }, |
||
22 | 'public function test' : function() { |
||
23 | this.static_num = 4; // doesn't actually exist in the instance scope |
||
24 | this.instance_num = 5; |
||
25 | return false; |
||
26 | }, |
||
27 | 'public function test2' : function() { |
||
28 | TestClass1.static_num = 6; |
||
29 | return true; |
||
30 | }, |
||
31 | 'public function test3' : function() { |
||
32 | TestClass1.static_num = 7; |
||
33 | return true; |
||
34 | }, |
||
35 | 'public static function testGet()' : function() { |
||
36 | return TestClass1.getStaticProtectedNum(); |
||
37 | } |
||
38 | |||
39 | }}); |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
40 | |||
41 | var a1 = new TestClass1(); |
||
42 | |||
43 | // try setting static members from within a static function |
||
44 | assert.strictEqual(TestClass1.getStaticNum(), 1, "TestClass1.getStaticNum() == 1"); |
||
45 | assert.strictEqual(TestClass1.test(), true, "Static function TestClass1.test() called successfully"); |
||
46 | assert.strictEqual(TestClass1.getStaticNum(), 2, "TestClass1.getStaticNum() == 2"); |
||
47 | |||
48 | //verify initial instance member value - TestClass1.test() attempted to change it using "this" from within a static function (shouldn't have worked) |
||
49 | assert.strictEqual(a1.getInstanceNum(), 1, "a1.getInstanceNum() == 1"); |
||
50 | |||
51 | assert.strictEqual(a1.test(), false, "Instance function a1.test() called successfully"); |
||
52 | assert.strictEqual(a1.getInstanceNum(), 5, "a1.getInstanceNum() == 5"); |
||
53 | assert.strictEqual(TestClass1.getStaticNum(), 2, "TestClass1.getStaticNum() == 2"); |
||
54 | |||
55 | assert.strictEqual(a1.test2(), true, "a1.test2() == true"); |
||
56 | assert.strictEqual(TestClass1.getStaticNum(), 6, "TestClass1.getStaticNum() == 6"); |
||
57 | |||
58 | assert.strictEqual(a1.test3(), true, "a1.test2() == true"); |
||
59 | assert.strictEqual(TestClass1.getStaticNum(), 7, "TestClass1.getStaticNum() == 7"); |
||
60 | |||
61 | assert.strictEqual(TestClass1.testGet(), 1, "TestClass1.testGet() == 1"); |
||
62 | |||
63 | |||
64 | |||
65 | var TestClass2 = JOII.ClassBuilder("TestClass2", {'extends': TestClass1}, function (TestClass2) { return { |
||
66 | 'public static immutable string static_str' : 'test', |
||
67 | 'public static function test(string)' : function(str) { |
||
68 | TestClass2.static_str = str; |
||
69 | }, |
||
70 | 'public static function test(number)' : function(num) { |
||
71 | TestClass2.setStaticProtectedNum(num); |
||
72 | } |
||
73 | }}); |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
74 | |||
75 | |||
76 | var a2 = new TestClass2(); |
||
77 | |||
78 | // try setting static members from within a static function (inherited). Should be affecting the member in TestClass1. |
||
79 | assert.strictEqual(TestClass2.getStaticNum(), 7, "TestClass2.getStaticNum() == 7"); |
||
80 | assert.strictEqual(TestClass2.test(), true, "Static function TestClass2.test() called successfully"); |
||
81 | assert.strictEqual(TestClass2.getStaticNum(), 2, "TestClass2.getStaticNum() == 2"); |
||
82 | assert.strictEqual(TestClass1.getStaticNum(), 2, "TestClass1.getStaticNum() == 2"); |
||
83 | |||
84 | //verify initial instance member value - TestClass2.test() attempted to change it using "this" from within a static function (shouldn't have worked) |
||
85 | assert.strictEqual(a2.getInstanceNum(), 1, "a2.getInstanceNum() == 1"); |
||
86 | |||
87 | assert.strictEqual(a2.test(), false, "Instance function a2.test() called successfully"); |
||
88 | assert.strictEqual(a2.getInstanceNum(), 5, "a2.getInstanceNum() == 5"); |
||
89 | assert.strictEqual(TestClass2.getStaticNum(), 2, "TestClass2.getStaticNum() == 2"); |
||
90 | assert.strictEqual(TestClass1.getStaticNum(), 2, "TestClass1.getStaticNum() == 2"); |
||
91 | |||
92 | assert.strictEqual(a2.test2(), true, "a2.test2() == true"); |
||
93 | assert.strictEqual(TestClass2.getStaticNum(), 6, "TestClass2.getStaticNum() == 6"); |
||
94 | assert.strictEqual(TestClass1.getStaticNum(), 6, "TestClass1.getStaticNum() == 6"); |
||
95 | |||
96 | assert.strictEqual(a2.test3(), true, "a2.test2() == true"); |
||
97 | assert.strictEqual(TestClass2.getStaticNum(), 7, "TestClass2.getStaticNum() == 7"); |
||
98 | assert.strictEqual(TestClass1.getStaticNum(), 7, "TestClass1.getStaticNum() == 7"); |
||
99 | |||
100 | TestClass2.setStaticNum(8); |
||
101 | assert.strictEqual(TestClass2.getStaticNum(), 8, "TestClass2.getStaticNum() == 8"); |
||
102 | assert.strictEqual(TestClass1.getStaticNum(), 8, "TestClass1.getStaticNum() == 8"); |
||
103 | |||
104 | assert.strictEqual(TestClass2.testGet(), 1, "TestClass2.testGet() == 1"); |
||
105 | |||
106 | TestClass2.test(2); |
||
107 | assert.strictEqual(TestClass1.testGet(), 2, "TestClass1.testGet() == 2"); |
||
108 | assert.strictEqual(TestClass2.testGet(), 2, "TestClass2.testGet() == 2"); |
||
109 | |||
110 | |||
111 | assert.throws(function() { |
||
112 | TestClass2.setStaticProtectedNum(2); |
||
113 | }, function(err) { return err.message === 'TestClass2.setStaticProtectedNum is not a function'; }, 'Validate: Static protected visibility.'); |
||
114 | |||
115 | |||
116 | assert.throws(function() { |
||
117 | TestClass2.setStaticStr('new test'); |
||
118 | }, function(err) { return err.message === 'TestClass2.setStaticStr is not a function'; }, 'Validate: Static immutable.'); |
||
119 | |||
120 | assert.strictEqual(TestClass2.getStaticStr(), 'test', "TestClass2.getStaticStr() == 'test'"); |
||
121 | |||
122 | assert.throws(function() { |
||
123 | TestClass1.getStaticStr(); |
||
124 | }, function(err) { return err.message === 'TestClass1.getStaticStr is not a function'; }, 'Validate: TestClass1.getStaticStr doesn\'t exist'); |
||
125 | |||
126 | |||
127 | var TestClass3 = JOII.ClassBuilder("TestClass3", {'extends': TestClass2}, function (TestClass3) { return { |
||
128 | |||
129 | }}); |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
130 | |||
131 | |||
132 | // overloaded static method on an inherited class, changing immutable static member |
||
133 | TestClass3.test('new test'); |
||
134 | |||
135 | assert.throws(function() { |
||
136 | TestClass3.setStaticStr('newer test'); |
||
137 | }, function(err) { return err.message === 'TestClass3.setStaticStr is not a function'; }, 'Validate: Static immutable.'); |
||
138 | |||
139 | assert.strictEqual(TestClass3.getStaticStr(), 'new test', "TestClass3.getStaticStr() == 'new test'"); |
||
140 | assert.strictEqual(TestClass2.getStaticStr(), 'new test', "TestClass2.getStaticStr() == 'new test'"); |
||
141 | |||
142 | |||
143 | var a3 = new TestClass3(); |
||
144 | |||
145 | // try setting static members from within a static function (inherited). Should be affecting the member in TestClass1. |
||
146 | assert.strictEqual(TestClass3.getStaticNum(), 8, "TestClass3.getStaticNum() == 8"); |
||
147 | assert.strictEqual(TestClass3.test(), true, "Static function TestClass3.test() called successfully"); |
||
148 | assert.strictEqual(TestClass3.getStaticNum(), 2, "TestClass3.getStaticNum() == 2"); |
||
149 | assert.strictEqual(TestClass1.getStaticNum(), 2, "TestClass1.getStaticNum() == 2"); |
||
150 | |||
151 | //verify initial instance member value - TestClass3.test() attempted to change it using "this" from within a static function (shouldn't have worked) |
||
152 | assert.strictEqual(a3.getInstanceNum(), 1, "a3.getInstanceNum() == 1"); |
||
153 | |||
154 | assert.strictEqual(a3.test(), false, "Instance function a3.test() called successfully"); |
||
155 | assert.strictEqual(a3.getInstanceNum(), 5, "a3.getInstanceNum() == 5"); |
||
156 | assert.strictEqual(TestClass3.getStaticNum(), 2, "TestClass3.getStaticNum() == 2"); |
||
157 | assert.strictEqual(TestClass1.getStaticNum(), 2, "TestClass1.getStaticNum() == 2"); |
||
158 | |||
159 | assert.strictEqual(a3.test2(), true, "a3.test2() == true"); |
||
160 | assert.strictEqual(TestClass3.getStaticNum(), 6, "TestClass3.getStaticNum() == 6"); |
||
161 | assert.strictEqual(TestClass1.getStaticNum(), 6, "TestClass1.getStaticNum() == 6"); |
||
162 | |||
163 | assert.strictEqual(a3.test3(), true, "a3.test2() == true"); |
||
164 | assert.strictEqual(TestClass3.getStaticNum(), 7, "TestClass3.getStaticNum() == 7"); |
||
165 | assert.strictEqual(TestClass1.getStaticNum(), 7, "TestClass1.getStaticNum() == 7"); |
||
166 | |||
167 | |||
168 | |||
169 | |||
170 | var TestStaticInterface = JOII.InterfaceBuilder('TestStaticInterface', { |
||
171 | 'public nullable string name' : null, |
||
172 | 'protected static number age' : null, |
||
173 | 'public static function myTest(string)' : function(a) {} |
||
174 | }); |
||
175 | |||
176 | |||
177 | |||
178 | assert.throws(function() { |
||
179 | var InterfaceTestClass = JOII.ClassBuilder("InterfaceTestClass", {'implements': TestStaticInterface}, function (InterfaceTestClass) { return { |
||
180 | 'public static nullable string name' : null, |
||
181 | 'protected static number age' : null, |
||
182 | 'public static function myTest(string)' : function(a) {} |
||
183 | }}); |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
184 | }, function(err) { return err === 'Class must implement public nullable string "name" as defined in the interface TestStaticInterface.'; }, 'Validate: Implementation must match non-static descriptor.'); |
||
185 | |||
186 | |||
187 | assert.throws(function() { |
||
188 | var InterfaceTestClass = JOII.ClassBuilder("InterfaceTestClass", {'implements': TestStaticInterface}, function (InterfaceTestClass) { return { |
||
189 | 'public nullable string name' : null, |
||
190 | 'protected number age' : null, |
||
191 | 'public static function myTest(string)' : function(a) {} |
||
192 | }}); |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
193 | }, function(err) { return err === 'Class must implement protected static number "age" as defined in the interface TestStaticInterface.'; }, 'Validate: Property implementation must match static descriptor.'); |
||
194 | |||
195 | assert.throws(function() { |
||
196 | var InterfaceTestClass = JOII.ClassBuilder("InterfaceTestClass", {'implements': TestStaticInterface}, function (InterfaceTestClass) { return { |
||
197 | 'public nullable string name' : null, |
||
198 | 'protected static number age' : null, |
||
199 | 'public function myTest(string)' : function(a) {} |
||
200 | }}); |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
201 | }, function(err) { return err === 'Class must implement public static function "myTest" as defined in the interface TestStaticInterface.'; }, 'Validate: Method implementation must match static descriptor.'); |
||
202 | |||
203 | assert.throws(function() { |
||
204 | var InterfaceTestClass = JOII.ClassBuilder("InterfaceTestClass", {'implements': TestStaticInterface}, function (InterfaceTestClass) { return { |
||
205 | 'public nullable string name' : null, |
||
206 | 'protected static number age' : null, |
||
207 | 'public static function myTest(number)' : function(a) {} |
||
208 | }}); |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
209 | }, function(err) { return err === 'Method myTest does not match the parameter types as defined in the interface TestStaticInterface.'; }, 'Validate: Method implementation must match static descriptor and parameter types.'); |
||
210 | |||
211 | // shouldn't throw anything |
||
212 | var InterfaceTestClass = JOII.ClassBuilder("InterfaceTestClass", {'implements': TestStaticInterface}, function (InterfaceTestClass) { return { |
||
213 | 'public nullable string name' : null, |
||
214 | 'protected static number age' : null, |
||
215 | 'public static function myTest(string)' : function(a) {} |
||
216 | }}); |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
217 | |||
218 | |||
219 | |||
220 | assert.throws(function() { |
||
221 | var StaticTestClass = JOII.ClassBuilder("StaticTestClass", {'static': true}, function (StaticTestClass) { return { |
||
222 | 'public string name' : null |
||
223 | }}); |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
224 | }, function(err) { return err === "Member name is non-static. A static class cannot contain non-static members."; }, 'Validate: Static class must contain only static members.'); |
||
225 | |||
226 | |||
227 | var StaticTestClass = JOII.ClassBuilder("StaticTestClass", {'static': true}, function (StaticTestClass) { return { |
||
228 | 'public static string person' : 'bob' |
||
229 | }}); |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
230 | |||
231 | assert.throws(function() { |
||
232 | var newTest = new StaticTestClass(); |
||
233 | }, function(err) { return err === "A static class cannot be instantiated."; }, 'Validate: Static classes cannot be instantiated.'); |
||
234 | |||
235 | assert.strictEqual(StaticTestClass.getPerson(), 'bob', "StaticTestClass.getPerson() == 'bob'"); |
||
236 | StaticTestClass.setPerson('joe') |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
237 | assert.strictEqual(StaticTestClass.getPerson(), 'joe', "StaticTestClass.getPerson() == 'joe'"); |
||
238 | |||
239 | |||
240 | var TestClass4 = JOII.ClassBuilder("TestClass4", {}, function (TestClass4) { return { |
||
241 | 'public static TestClass4 instance' : null, |
||
242 | 'protected number num' : 1, |
||
243 | 'public static function construct' : function() { |
||
244 | TestClass4.instance = new TestClass4(); |
||
245 | }, |
||
246 | 'public static function test()' : function() { |
||
247 | return false; |
||
248 | }, |
||
249 | 'public function test()' : function() { |
||
250 | return true; |
||
251 | }, |
||
252 | '__call(string)' : function(str) { |
||
253 | return "Success: " + str; |
||
254 | }, |
||
255 | '__call(number)' : function(num) { |
||
256 | return num * 2; |
||
257 | }, |
||
258 | 'public static function test(number)' : function(num) { |
||
259 | return TestClass4(num); |
||
260 | }, |
||
261 | 'public static function test(string)' : function(str) { |
||
262 | return TestClass4(str); |
||
263 | } |
||
264 | }}); |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
265 | |||
266 | assert.strictEqual(TestClass4.getInstance().test(), true, "TestClass4.getInstance().test() == true"); |
||
267 | |||
268 | assert.throws(function() { |
||
269 | TestClass4.getInstance().getNum(); |
||
270 | }, function(err) { return err.message === "TestClass4.getInstance(...).getNum is not a function"; }, 'Validate: In class self instantiate returned outer scope.'); |
||
271 | |||
272 | assert.strictEqual(TestClass4.getInstance().test(), true, "TestClass4.getInstance().test() == true"); |
||
273 | |||
274 | assert.strictEqual(TestClass4.test("testing"), "Success: testing", "Testing in-class _call"); |
||
275 | assert.strictEqual(TestClass4.test(4), 8, "Testing in-class _call overload"); |
||
276 | |||
277 | |||
278 | }); |
||
279 |
Strict mode is a way to opt-in to a restricted variant of JavaScript. It eliminates some common pitfalls by being less lenient and raising more errors.
Besides, it is also used to fix certain mistakes which made it difficult for JavaScript runtimes to perform certain optimizations.
We generally recommend to only enable strict mode on the function scope and not in the global scope as that might break third-party scripts on your website.