Pop-up dictionary browser extension for language learning. Successor to Yomichan. (PERSONAL FORK)
at lambda-fork/main 319 lines 10 kB view raw
1/* 2 * Copyright (C) 2023-2025 Yomitan Authors 3 * Copyright (C) 2020-2022 Yomichan Authors 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <https://www.gnu.org/licenses/>. 17 */ 18 19import {describe, expect, test} from 'vitest'; 20import {DynamicProperty} from '../ext/js/core/dynamic-property.js'; 21import {deepEqual} from '../ext/js/core/utilities.js'; 22 23describe('DynamicProperty', () => { 24 /** @type {import('test/core').DynamicPropertyTestData} */ 25 const data = [ 26 { 27 initialValue: 0, 28 operations: [ 29 { 30 operation: null, 31 args: [0], 32 expectedDefaultValue: 0, 33 expectedValue: 0, 34 expectedOverrideCount: 0, 35 expectedEventOccurred: false, 36 }, 37 { 38 operation: 'set.defaultValue', 39 args: [1], 40 expectedDefaultValue: 1, 41 expectedValue: 1, 42 expectedOverrideCount: 0, 43 expectedEventOccurred: true, 44 }, 45 { 46 operation: 'set.defaultValue', 47 args: [1], 48 expectedDefaultValue: 1, 49 expectedValue: 1, 50 expectedOverrideCount: 0, 51 expectedEventOccurred: false, 52 }, 53 { 54 operation: 'set.defaultValue', 55 args: [0], 56 expectedDefaultValue: 0, 57 expectedValue: 0, 58 expectedOverrideCount: 0, 59 expectedEventOccurred: true, 60 }, 61 { 62 operation: 'setOverride', 63 args: [8], 64 expectedDefaultValue: 0, 65 expectedValue: 8, 66 expectedOverrideCount: 1, 67 expectedEventOccurred: true, 68 }, 69 { 70 operation: 'setOverride', 71 args: [16], 72 expectedDefaultValue: 0, 73 expectedValue: 8, 74 expectedOverrideCount: 2, 75 expectedEventOccurred: false, 76 }, 77 { 78 operation: 'setOverride', 79 args: [32, 1], 80 expectedDefaultValue: 0, 81 expectedValue: 32, 82 expectedOverrideCount: 3, 83 expectedEventOccurred: true, 84 }, 85 { 86 operation: 'setOverride', 87 args: [64, -1], 88 expectedDefaultValue: 0, 89 expectedValue: 32, 90 expectedOverrideCount: 4, 91 expectedEventOccurred: false, 92 }, 93 { 94 operation: 'clearOverride', 95 args: [-4], 96 expectedDefaultValue: 0, 97 expectedValue: 32, 98 expectedOverrideCount: 3, 99 expectedEventOccurred: false, 100 }, 101 { 102 operation: 'clearOverride', 103 args: [-3], 104 expectedDefaultValue: 0, 105 expectedValue: 32, 106 expectedOverrideCount: 2, 107 expectedEventOccurred: false, 108 }, 109 { 110 operation: 'clearOverride', 111 args: [-2], 112 expectedDefaultValue: 0, 113 expectedValue: 64, 114 expectedOverrideCount: 1, 115 expectedEventOccurred: true, 116 }, 117 { 118 operation: 'clearOverride', 119 args: [-1], 120 expectedDefaultValue: 0, 121 expectedValue: 0, 122 expectedOverrideCount: 0, 123 expectedEventOccurred: true, 124 }, 125 ], 126 }, 127 ]; 128 129 describe.each(data)('Test DynamicProperty($initialValue)', ({initialValue, operations}) => { 130 test('works as expected', () => { 131 const property = new DynamicProperty(initialValue); 132 const overrideTokens = []; 133 let eventOccurred = false; 134 const onChange = () => { eventOccurred = true; }; 135 property.on('change', onChange); 136 for (const {operation, args, expectedDefaultValue, expectedValue, expectedOverrideCount, expectedEventOccurred} of operations) { 137 eventOccurred = false; 138 switch (operation) { 139 case 'set.defaultValue': property.defaultValue = args[0]; break; 140 case 'setOverride': overrideTokens.push(property.setOverride(...args)); break; 141 case 'clearOverride': property.clearOverride(overrideTokens[overrideTokens.length + args[0]]); break; 142 } 143 expect(eventOccurred).toStrictEqual(expectedEventOccurred); 144 expect(property.defaultValue).toStrictEqual(expectedDefaultValue); 145 expect(property.value).toStrictEqual(expectedValue); 146 expect(property.overrideCount).toStrictEqual(expectedOverrideCount); 147 } 148 property.off('change', onChange); 149 }); 150 }); 151}); 152 153describe('deepEqual', () => { 154 /** @type {import('test/core').DeepEqualTestData} */ 155 const simpleTestsData = [ 156 { 157 value1: 0, 158 value2: 0, 159 expected: true, 160 }, 161 { 162 value1: null, 163 value2: null, 164 expected: true, 165 }, 166 { 167 value1: 'test', 168 value2: 'test', 169 expected: true, 170 }, 171 { 172 value1: true, 173 value2: true, 174 expected: true, 175 }, 176 { 177 value1: 0, 178 value2: 1, 179 expected: false, 180 }, 181 { 182 value1: null, 183 value2: false, 184 expected: false, 185 }, 186 { 187 value1: 'test1', 188 value2: 'test2', 189 expected: false, 190 }, 191 { 192 value1: true, 193 value2: false, 194 expected: false, 195 }, 196 ]; 197 /** @type {import('test/core').DeepEqualTestData} */ 198 const simpleObjectTestsData = [ 199 { 200 value1: {}, 201 value2: {}, 202 expected: true, 203 }, 204 { 205 value1: {}, 206 value2: [], 207 expected: false, 208 }, 209 { 210 value1: [], 211 value2: [], 212 expected: true, 213 }, 214 { 215 value1: {}, 216 value2: null, 217 expected: false, 218 }, 219 ]; 220 /** @type {import('test/core').DeepEqualTestData} */ 221 const complexObjectTestsData = [ 222 { 223 value1: [1], 224 value2: [], 225 expected: false, 226 }, 227 { 228 value1: [1], 229 value2: [1], 230 expected: true, 231 }, 232 { 233 value1: [1], 234 value2: [2], 235 expected: false, 236 }, 237 238 { 239 value1: {}, 240 value2: {test: 1}, 241 expected: false, 242 }, 243 { 244 value1: {test: 1}, 245 value2: {test: 1}, 246 expected: true, 247 }, 248 { 249 value1: {test: 1}, 250 value2: {test: {test2: false}}, 251 expected: false, 252 }, 253 { 254 value1: {test: {test2: true}}, 255 value2: {test: {test2: false}}, 256 expected: false, 257 }, 258 { 259 value1: {test: {test2: [true]}}, 260 value2: {test: {test2: [true]}}, 261 expected: true, 262 }, 263 ]; 264 /** @type {import('test/core').DeepEqualTestData} */ 265 const recursiveTestsData = [ 266 { 267 value1: (() => { 268 const x = {}; 269 x.x = x; 270 return x; 271 })(), 272 value2: (() => { 273 const x = {}; 274 x.x = x; 275 return x; 276 })(), 277 expected: false, 278 }, 279 ]; 280 describe('simple tests', () => { 281 test.each(simpleTestsData)('deepEqual($value1, $value2) -> $expected', ({value1, value2, expected}) => { 282 const actual1 = deepEqual(value1, value2); 283 expect(actual1).toStrictEqual(expected); 284 285 const actual2 = deepEqual(value2, value1); 286 expect(actual2).toStrictEqual(expected); 287 }); 288 }); 289 290 describe('simple object tests', () => { 291 test.each(simpleObjectTestsData)('deepEqual($value1, $value2) -> $expected', ({value1, value2, expected}) => { 292 const actual1 = deepEqual(value1, value2); 293 expect(actual1).toStrictEqual(expected); 294 295 const actual2 = deepEqual(value2, value1); 296 expect(actual2).toStrictEqual(expected); 297 }); 298 }); 299 300 describe('complex object tests', () => { 301 test.each(complexObjectTestsData)('deepEqual($value1, $value2) -> $expected', ({value1, value2, expected}) => { 302 const actual1 = deepEqual(value1, value2); 303 expect(actual1).toStrictEqual(expected); 304 305 const actual2 = deepEqual(value2, value1); 306 expect(actual2).toStrictEqual(expected); 307 }); 308 }); 309 310 describe('recursive tests', () => { 311 test.each(recursiveTestsData)('deepEqual($value1, $value2) -> $expected', ({value1, value2, expected}) => { 312 const actual1 = deepEqual(value1, value2); 313 expect(actual1).toStrictEqual(expected); 314 315 const actual2 = deepEqual(value2, value1); 316 expect(actual2).toStrictEqual(expected); 317 }); 318 }); 319});