braid-text 0.2.106 → 0.2.108

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.
package/test/test.html DELETED
@@ -1,118 +0,0 @@
1
- <style>
2
- body {
3
- font-family: Arial, sans-serif;
4
- max-width: 800px;
5
- margin: 0 auto;
6
- padding: 10px;
7
- }
8
- .test {
9
- margin-bottom: 3px;
10
- padding: 3px;
11
- }
12
- .running {
13
- background-color: #fffde7;
14
- }
15
- .passed {
16
- background-color: #e8f5e9;
17
- }
18
- .failed {
19
- background-color: #ffebee;
20
- }
21
- #summaryContainer {
22
- display: flex;
23
- flex-wrap: wrap;
24
- gap: 5px;
25
- margin-bottom: 20px;
26
- }
27
- .summaryBox {
28
- width: 25px;
29
- height: 25px;
30
- border: 1px solid #ddd;
31
- }
32
- </style>
33
- <script src="https://unpkg.com/braid-http@~1.3/braid-http-client.js"></script>
34
- <script src="./tests.js"></script>
35
- <div id="summaryContainer"></div>
36
- <div id="testContainer"></div>
37
- <script type=module>
38
-
39
- import {
40
- default as init,
41
- Doc,
42
- OpLog,
43
- } from "https://unpkg.com/diamond-types-web";
44
-
45
- // Make diamond-types available globally for tests.js
46
- window.Doc = Doc
47
- window.OpLog = OpLog
48
- window.dt_p = init()
49
-
50
- braid_fetch.enable_multiplex = false
51
-
52
- // Parse URL parameters for filter
53
- const urlParams = new URLSearchParams(window.location.search)
54
- const filterArg = urlParams.get('filter') || urlParams.get('grep')
55
-
56
- let delay = 0
57
-
58
- function createTestDiv(testName) {
59
- const div = document.createElement("div")
60
- div.className = "test running"
61
- div.innerHTML = `<span style="font-weight:bold">${testName}: </span><span class="result">Running...</span>`
62
- testContainer.appendChild(div)
63
- return div
64
- }
65
-
66
- function updateTestResult(div, passed, message, got, expected) {
67
- div.className = `test ${passed ? "passed" : "failed"}`
68
-
69
- if (passed) {
70
- div.querySelector(".result").textContent = message
71
- div.querySelector(".result").style.fontSize = message.length > 400 ? 'xx-small' : message.length > 100 ? 'small' : ''
72
- } else {
73
- div.querySelector(".result").innerHTML = `${message}<br><strong>Got:</strong> ${got}<br><strong>Expected:</strong> ${expected}`
74
- }
75
- }
76
-
77
- function createSummaryBox() {
78
- var summaryContainer = document.getElementById('summaryContainer')
79
- const box = document.createElement('div');
80
- box.className = 'summaryBox running';
81
- summaryContainer.appendChild(box);
82
- return box;
83
- }
84
-
85
- function updateSummaryBox(box, passed) {
86
- box.className = `summaryBox ${passed ? 'passed' : passed === false ? 'failed' : 'other'}`;
87
- }
88
-
89
- async function runTest(testName, testFunction, expectedResult) {
90
- // Apply filter if specified
91
- if (filterArg && !testName.toLowerCase().includes(filterArg.toLowerCase())) {
92
- return // Skip this test
93
- }
94
-
95
- delay += 70
96
-
97
- await new Promise(done => setTimeout(done, delay))
98
- const div = createTestDiv(testName)
99
- const summaryBox = createSummaryBox()
100
- try {
101
- let x = await testFunction()
102
- if (x == expectedResult) {
103
- updateTestResult(div, true, x)
104
- updateSummaryBox(summaryBox, true)
105
- } else {
106
- updateTestResult(div, false, "Mismatch:", x, expectedResult)
107
- updateSummaryBox(summaryBox, false)
108
- }
109
- } catch (error) {
110
- updateTestResult(div, false, "Error:", error.message || error, expectedResult)
111
- updateSummaryBox(summaryBox, false)
112
- }
113
- }
114
-
115
- // Load and run all tests from the shared tests.js file
116
- defineTests(runTest, braid_fetch)
117
-
118
- </script>
package/test/test.js DELETED
@@ -1,321 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // Unified test runner - can run in console mode (Node.js) or browser mode (server)
4
- const http = require('http')
5
- const {fetch: braid_fetch} = require('braid-http')
6
- const defineTests = require('./tests.js')
7
-
8
- // Parse command line arguments
9
- const args = process.argv.slice(2)
10
- const mode = args.includes('--browser') || args.includes('-b') ? 'browser' : 'console'
11
- const portArg = args.find(arg => arg.startsWith('--port='))?.split('=')[1]
12
- || args.find(arg => !arg.startsWith('-') && !isNaN(arg))
13
- const port = portArg || 8889
14
- const filterArg = args.find(arg => arg.startsWith('--filter='))?.split('=')[1]
15
- || args.find(arg => arg.startsWith('--grep='))?.split('=')[1]
16
-
17
- // Show help if requested
18
- if (args.includes('--help') || args.includes('-h')) {
19
- console.log(`
20
- Usage: node test.js [options]
21
-
22
- Options:
23
- --browser, -b Start server for browser testing (default: console mode)
24
- --port=PORT Specify port number (default: 8889)
25
- PORT Port number as positional argument
26
- --filter=PATTERN Only run tests matching pattern (case-insensitive)
27
- --grep=PATTERN Alias for --filter
28
- --help, -h Show this help message
29
-
30
- Examples:
31
- node test.js # Run all tests in console
32
- node test.js --filter="sync" # Run only tests with "sync" in name
33
- node test.js --grep="digest" # Run only tests with "digest" in name
34
- node test.js --browser # Start browser test server
35
- node test.js --browser --port=9000
36
- node test.js -b 9000 # Short form with port
37
- `)
38
- process.exit(0)
39
- }
40
-
41
- // ============================================================================
42
- // Shared Server Code
43
- // ============================================================================
44
-
45
- function createTestServer(options = {}) {
46
- const {
47
- port = 8889,
48
- runTests = false,
49
- logRequests = false
50
- } = options
51
-
52
- const braid_text = require(`${__dirname}/../index.js`)
53
- braid_text.db_folder = `${__dirname}/test_db_folder`
54
-
55
- const braid_text2 = braid_text.create_braid_text()
56
- braid_text2.db_folder = null
57
-
58
- const server = http.createServer(async (req, res) => {
59
- if (logRequests) {
60
- console.log(`${req.method} ${req.url}`)
61
- }
62
-
63
- // Free the CORS
64
- braid_text.free_cors(res)
65
- if (req.method === 'OPTIONS') return
66
-
67
- if (req.url.startsWith('/have_error')) {
68
- res.statusCode = 569
69
- return res.end('error')
70
- }
71
-
72
- if (req.url.startsWith('/unauthorized') && req.method === 'PUT') {
73
- res.statusCode = 401
74
- return res.end('Unauthorized')
75
- }
76
-
77
- if (req.url.startsWith('/forbidden') && req.method === 'PUT') {
78
- res.statusCode = 403
79
- return res.end('Forbidden')
80
- }
81
-
82
- if (req.url.startsWith('/server_error') && req.method === 'PUT') {
83
- res.statusCode = 500
84
- return res.end('Internal Server Error')
85
- }
86
-
87
- if (req.url.startsWith('/404')) {
88
- res.statusCode = 404
89
- return res.end('Not Found')
90
- }
91
-
92
- if (req.url.startsWith('/eval')) {
93
- var body = await new Promise(done => {
94
- var chunks = []
95
- req.on('data', chunk => chunks.push(chunk))
96
- req.on('end', () => done(Buffer.concat(chunks)))
97
- })
98
- try {
99
- eval('' + body)
100
- } catch (error) {
101
- res.writeHead(500, { 'Content-Type': 'text/plain' })
102
- res.end(`Error: ${error.message}`)
103
- }
104
- return
105
- }
106
-
107
- if (req.url.startsWith('/test.html')) {
108
- let parts = req.url.split(/[\?&=]/g)
109
-
110
- if (parts[1] === 'check') {
111
- res.writeHead(200, { "Content-Type": "application/json", "Cache-Control": "no-cache" })
112
- return res.end(JSON.stringify({
113
- checking: parts[2],
114
- result: (await braid_text.get(parts[2])) != null
115
- }))
116
- } else if (parts[1] === 'dt_create_bytes_big_name') {
117
- try {
118
- braid_text.dt_create_bytes('x'.repeat(1000000) + '-0', [], 0, 0, 'hi')
119
- return res.end(JSON.stringify({ ok: true }))
120
- } catch (e) {
121
- return res.end(JSON.stringify({ ok: false, error: '' + e }))
122
- }
123
- } else if (parts[1] === 'dt_create_bytes_many_names') {
124
- try {
125
- braid_text.dt_create_bytes('hi-0', new Array(1000000).fill(0).map((x, i) => `x${i}-0`), 0, 0, 'hi')
126
- return res.end(JSON.stringify({ ok: true }))
127
- } catch (e) {
128
- return res.end(JSON.stringify({ ok: false, error: '' + e }))
129
- }
130
- }
131
-
132
- res.writeHead(200, { "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-cache" })
133
- require("fs").createReadStream(`${__dirname}/test.html`).pipe(res)
134
- return
135
- }
136
-
137
- // Serve tests.js file for browser
138
- if (req.url.startsWith('/tests.js')) {
139
- res.writeHead(200, { "Content-Type": "application/javascript; charset=utf-8", "Cache-Control": "no-cache" })
140
- require("fs").createReadStream(`${__dirname}/tests.js`).pipe(res)
141
- return
142
- }
143
-
144
- // Now serve the collaborative text!
145
- braid_text.serve(req, res)
146
- })
147
-
148
- return {
149
- server,
150
- start: () => new Promise((resolve) => {
151
- server.listen(port, 'localhost', () => {
152
- if (runTests) {
153
- console.log(`Test server running on http://localhost:${port}`)
154
- } else {
155
- console.log(`serving: http://localhost:${port}/test.html`)
156
- }
157
- resolve()
158
- })
159
- }),
160
- port
161
- }
162
- }
163
-
164
- // ============================================================================
165
- // Console Test Mode (Node.js)
166
- // ============================================================================
167
-
168
- async function runConsoleTests() {
169
- // Test tracking
170
- let totalTests = 0
171
- let passedTests = 0
172
- let failedTests = 0
173
-
174
- // Handle unhandled rejections during tests (some tests intentionally cause errors)
175
- const unhandledRejections = []
176
- process.on('unhandledRejection', (reason, promise) => {
177
- // Collect but don't crash - some tests intentionally trigger errors
178
- unhandledRejections.push({ reason, promise })
179
- })
180
-
181
- // Node.js test runner implementation
182
- // Store tests to run sequentially instead of in parallel
183
- const testsToRun = []
184
-
185
- function runTest(testName, testFunction, expectedResult) {
186
- // Apply filter if specified
187
- if (filterArg && !testName.toLowerCase().includes(filterArg.toLowerCase())) {
188
- return // Skip this test
189
- }
190
-
191
- totalTests++
192
- testsToRun.push({ testName, testFunction, expectedResult })
193
- }
194
-
195
- // Create a braid_fetch wrapper that points to localhost
196
- function createBraidFetch(baseUrl) {
197
- return async (url, options = {}) => {
198
- const fullUrl = url.startsWith('http') ? url : `${baseUrl}${url}`
199
- return braid_fetch(fullUrl, options)
200
- }
201
- }
202
-
203
- console.log('Starting braid-text tests...\n')
204
-
205
- // Create and start the test server
206
- const testServer = createTestServer({
207
- port,
208
- runTests: true,
209
- logRequests: false
210
- })
211
-
212
- await testServer.start()
213
-
214
- // Create braid_fetch bound to test server
215
- const testBraidFetch = createBraidFetch(`http://localhost:${port}`)
216
-
217
- // Load the real diamond-types module for Node.js
218
- const { Doc, OpLog } = require('@braid.org/diamond-types-node')
219
-
220
- // Define globals needed for some tests
221
- global.Doc = Doc
222
- global.OpLog = OpLog
223
- global.dt_p = Promise.resolve() // No initialization needed for Node.js version
224
- global.fetch = testBraidFetch
225
- global.AbortController = AbortController
226
- global.crypto = require('crypto').webcrypto
227
-
228
- // Run all tests
229
- defineTests(runTest, testBraidFetch)
230
-
231
- // Run tests sequentially (not in parallel) to avoid conflicts
232
- for (const { testName, testFunction, expectedResult } of testsToRun) {
233
- try {
234
- const result = await testFunction()
235
- if (result == expectedResult) {
236
- passedTests++
237
- console.log(`✓ ${testName}`)
238
- } else {
239
- failedTests++
240
- console.log(`✗ ${testName}`)
241
- console.log(` Expected: ${expectedResult}`)
242
- console.log(` Got: ${result}`)
243
- }
244
- } catch (error) {
245
- failedTests++
246
- console.log(`✗ ${testName}`)
247
- console.log(` Error: ${error.message || error}`)
248
- }
249
- }
250
-
251
- // Print summary
252
- console.log('\n' + '='.repeat(50))
253
- console.log(`Total: ${totalTests} | Passed: ${passedTests} | Failed: ${failedTests}`)
254
- console.log('='.repeat(50))
255
-
256
- // Clean up test database folder
257
- console.log('Cleaning up test database folder...')
258
- const fs = require('fs')
259
- const path = require('path')
260
- const testDbPath = path.join(__dirname, 'test_db_folder')
261
- try {
262
- if (fs.existsSync(testDbPath)) {
263
- fs.rmSync(testDbPath, { recursive: true, force: true })
264
- console.log('Test database folder removed')
265
- }
266
- } catch (err) {
267
- console.log(`Warning: Could not remove test database folder: ${err.message}`)
268
- }
269
-
270
- // Force close the server and all connections
271
- console.log('Closing server...')
272
- testServer.server.close(() => {
273
- console.log('Server closed callback - calling process.exit()')
274
- process.exit(failedTests > 0 ? 1 : 0)
275
- })
276
-
277
- // Also close all active connections if the method exists (Node 18.2+)
278
- if (typeof testServer.server.closeAllConnections === 'function') {
279
- console.log('Closing all connections...')
280
- testServer.server.closeAllConnections()
281
- }
282
-
283
- // Fallback: force exit after a short delay even if server hasn't fully closed
284
- console.log('Setting 200ms timeout fallback...')
285
- setTimeout(() => {
286
- console.log('Timeout reached - calling process.exit()')
287
- process.exit(failedTests > 0 ? 1 : 0)
288
- }, 200)
289
- }
290
-
291
- // ============================================================================
292
- // Browser Test Mode (Server)
293
- // ============================================================================
294
-
295
- async function runBrowserMode() {
296
- const testServer = createTestServer({
297
- port,
298
- runTests: false,
299
- logRequests: true
300
- })
301
-
302
- await testServer.start()
303
- }
304
-
305
- // ============================================================================
306
- // Main Entry Point
307
- // ============================================================================
308
-
309
- async function main() {
310
- if (mode === 'browser') {
311
- await runBrowserMode()
312
- } else {
313
- await runConsoleTests()
314
- }
315
- }
316
-
317
- // Run the appropriate mode
318
- main().catch(err => {
319
- console.error('Fatal error:', err)
320
- process.exit(1)
321
- })