@mblaney/holster 1.0.16 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,47 @@
1
+ import fs from "fs"
2
+ import {Server} from "mock-socket"
3
+ import {describe, test} from "node:test"
4
+ import assert from "node:assert/strict"
5
+ import Holster from "../../src/holster.js"
6
+
7
+ describe("system - promise wrapped calls", () => {
8
+ const wss = new Server("ws://localhost:9004")
9
+ const holster = Holster({file: "test/system/promise-wrapper", wss: wss})
10
+
11
+ test("promise wrapped get returns null for missing key", async t => {
12
+ const data = await new Promise(res => {
13
+ holster.get("missing", res)
14
+ })
15
+ assert.equal(data, null)
16
+ })
17
+
18
+ test("promise wrapped get returns data for existing key", async t => {
19
+ await new Promise(res => {
20
+ holster.get("key").put({value: "test"}, res)
21
+ })
22
+
23
+ const data = await new Promise(res => {
24
+ holster.get("key", res)
25
+ })
26
+ assert.notEqual(data, null)
27
+ assert.equal(data.value, "test")
28
+ })
29
+
30
+ test("promise wrapped next returns null for missing nested key", async t => {
31
+ const data = await new Promise(res => {
32
+ holster.get("key1").next("missing", res)
33
+ })
34
+ assert.equal(data, null)
35
+ })
36
+
37
+ test("cleanup", (t, done) => {
38
+ fs.rm(
39
+ "test/system/promise-wrapper",
40
+ {recursive: true, force: true},
41
+ err => {
42
+ assert.equal(err, null)
43
+ done()
44
+ },
45
+ )
46
+ })
47
+ })
@@ -0,0 +1,56 @@
1
+ import fs from "fs"
2
+ import {Server} from "mock-socket"
3
+ import {describe, test} from "node:test"
4
+ import assert from "node:assert/strict"
5
+ import Holster from "../../src/holster.js"
6
+
7
+ describe("system - user chained get with on", () => {
8
+ const wss = new Server("ws://localhost:9012")
9
+ const holster = Holster({file: "test/system/user-chained-on", wss: wss})
10
+ const user = holster.user()
11
+
12
+ test("user create and auth", (t, done) => {
13
+ user.create("testuser", "password", err => {
14
+ assert.equal(err, null)
15
+ user.auth("testuser", "password", err => {
16
+ assert.equal(err, null)
17
+ done()
18
+ })
19
+ })
20
+ })
21
+
22
+ test("on listener fires with null when no data exists", (t, done) => {
23
+ user.get("key").on(data => {
24
+ // This is the actual behavior - on fires with null for non-existent keys
25
+ assert.equal(data, null)
26
+ done()
27
+ }, true)
28
+ })
29
+
30
+ test("put then on listener receives data", (t, done) => {
31
+ // Put data first
32
+ user.get("key2").put({value: "test"}, err => {
33
+ assert.equal(err, null)
34
+
35
+ // Then set up listener - should get the existing data
36
+ setTimeout(() => {
37
+ user.get("key2").on(data => {
38
+ assert.notEqual(data, null)
39
+ assert.deepEqual(data, {value: "test"})
40
+ done()
41
+ }, true)
42
+ }, 50)
43
+ })
44
+ })
45
+
46
+ test("cleanup", (t, done) => {
47
+ fs.rm(
48
+ "test/system/user-chained-on",
49
+ {recursive: true, force: true},
50
+ err => {
51
+ assert.equal(err, null)
52
+ done()
53
+ },
54
+ )
55
+ })
56
+ })
@@ -0,0 +1,140 @@
1
+ import fs from "fs"
2
+ import {Server} from "mock-socket"
3
+ import {describe, test} from "node:test"
4
+ import assert from "node:assert/strict"
5
+ import Holster from "../../src/holster.js"
6
+
7
+ describe("system - user concurrent listeners", () => {
8
+ const wss = new Server("ws://localhost:9015")
9
+ const holster = Holster({
10
+ file: "test/system/user-concurrent-listeners",
11
+ wss: wss,
12
+ })
13
+ const user = holster.user()
14
+
15
+ test("user create and auth", (t, done) => {
16
+ user.create("testuser", "password", err => {
17
+ assert.equal(err, null)
18
+ user.auth("testuser", "password", err => {
19
+ assert.equal(err, null)
20
+ done()
21
+ })
22
+ })
23
+ })
24
+
25
+ test("multiple listeners on same path receive data", (t, done) => {
26
+ let listener1Called = false
27
+ let listener2Called = false
28
+
29
+ user.get("key").put({value: "test"}, err => {
30
+ assert.equal(err, null)
31
+
32
+ // Set up two listeners on the same path
33
+ user.get("key").on(data => {
34
+ listener1Called = true
35
+ assert.notEqual(data, null)
36
+ assert.deepEqual(data, {value: "test"})
37
+ checkComplete()
38
+ }, true)
39
+
40
+ user.get("key").on(data => {
41
+ listener2Called = true
42
+ assert.notEqual(data, null)
43
+ assert.deepEqual(data, {value: "test"})
44
+ checkComplete()
45
+ }, true)
46
+
47
+ function checkComplete() {
48
+ if (listener1Called && listener2Called) {
49
+ done()
50
+ }
51
+ }
52
+ })
53
+ })
54
+
55
+ test("nested listeners on parent and child paths", (t, done) => {
56
+ let parentCalled = false
57
+ let childCalled = false
58
+
59
+ user.get("parent").put({value: "parent-value"}, err => {
60
+ assert.equal(err, null)
61
+
62
+ user
63
+ .get("parent")
64
+ .next("child")
65
+ .put({value: "child-value"}, err => {
66
+ assert.equal(err, null)
67
+
68
+ // Listen on parent
69
+ user.get("parent").on(data => {
70
+ parentCalled = true
71
+ assert.notEqual(data, null)
72
+ assert.equal(data.value, "parent-value")
73
+ // Parent includes child as a rel
74
+ assert.notEqual(data.child, undefined)
75
+ checkComplete()
76
+ }, true)
77
+
78
+ // Listen on child
79
+ user
80
+ .get("parent")
81
+ .next("child")
82
+ .on(data => {
83
+ childCalled = true
84
+ assert.notEqual(data, null)
85
+ assert.deepEqual(data, {value: "child-value"})
86
+ checkComplete()
87
+ }, true)
88
+
89
+ function checkComplete() {
90
+ if (parentCalled && childCalled) {
91
+ done()
92
+ }
93
+ }
94
+ })
95
+ })
96
+ })
97
+
98
+ test("listener race condition - data before and after listener setup", (t, done) => {
99
+ const results = []
100
+
101
+ // Put data first
102
+ user.get("race").put({value: "first"}, err => {
103
+ assert.equal(err, null)
104
+
105
+ // Set up listener with _get=true to read existing data
106
+ user.get("race").on(data => {
107
+ results.push(data?.value)
108
+ }, true)
109
+
110
+ // Immediately put new data
111
+ setTimeout(() => {
112
+ user.get("race").put({value: "second"}, err => {
113
+ assert.equal(err, null)
114
+
115
+ setTimeout(() => {
116
+ // Should have received both values
117
+ assert.equal(
118
+ results.length >= 1,
119
+ true,
120
+ "Should receive at least initial value",
121
+ )
122
+ assert.equal(results[0], "first", "First value should be 'first'")
123
+ done()
124
+ }, 100)
125
+ })
126
+ }, 50)
127
+ })
128
+ })
129
+
130
+ test("cleanup", (t, done) => {
131
+ fs.rm(
132
+ "test/system/user-concurrent-listeners",
133
+ {recursive: true, force: true},
134
+ err => {
135
+ assert.equal(err, null)
136
+ done()
137
+ },
138
+ )
139
+ })
140
+ })
@@ -0,0 +1,64 @@
1
+ import fs from "fs"
2
+ import {Server} from "mock-socket"
3
+ import {describe, test} from "node:test"
4
+ import assert from "node:assert/strict"
5
+ import Holster from "../../src/holster.js"
6
+
7
+ describe("system - user listener before data", () => {
8
+ const wss = new Server("ws://localhost:9017")
9
+ const holster = Holster({
10
+ file: "test/system/user-listener-before-data",
11
+ wss: wss,
12
+ })
13
+ const user = holster.user()
14
+
15
+ test("user create and auth", (t, done) => {
16
+ user.create("testuser", "password", err => {
17
+ assert.equal(err, null)
18
+ user.auth("testuser", "password", err => {
19
+ assert.equal(err, null)
20
+ done()
21
+ })
22
+ })
23
+ })
24
+
25
+ test("listener set up before data exists receives data when populated", (t, done) => {
26
+ const results = []
27
+
28
+ // Set up listener first before data exists
29
+ user.get("testkey").on(data => {
30
+ results.push(data)
31
+ })
32
+
33
+ // Give listener time to set up
34
+ setTimeout(() => {
35
+ user.get("testkey").put({value: "test"}, err => {
36
+ assert.equal(err, null)
37
+
38
+ // Give listener time to fire
39
+ setTimeout(() => {
40
+ // Should have received the test value
41
+ const nonNull = results.filter(r => r !== null)
42
+ assert.equal(
43
+ nonNull.length >= 1,
44
+ true,
45
+ "Should have at least one non-null result",
46
+ )
47
+ assert.deepEqual(nonNull[0], {value: "test"})
48
+ done()
49
+ }, 200)
50
+ })
51
+ }, 100)
52
+ })
53
+
54
+ test("cleanup", (t, done) => {
55
+ fs.rm(
56
+ "test/system/user-listener-before-data",
57
+ {recursive: true, force: true},
58
+ err => {
59
+ assert.equal(err, null)
60
+ done()
61
+ },
62
+ )
63
+ })
64
+ })