stated-protocol-parser 1.0.3 → 1.0.5

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.
Files changed (82) hide show
  1. package/dist/constants.d.ts +1 -0
  2. package/dist/constants.d.ts.map +1 -0
  3. package/dist/constants.js +1 -0
  4. package/dist/constants.js.map +1 -0
  5. package/dist/esm/constants.d.ts +47 -0
  6. package/dist/esm/constants.d.ts.map +1 -0
  7. package/dist/esm/constants.js +47 -0
  8. package/dist/esm/constants.js.map +1 -0
  9. package/dist/esm/hash.browser.d.ts +31 -0
  10. package/dist/esm/hash.browser.d.ts.map +1 -0
  11. package/dist/esm/hash.browser.js +58 -0
  12. package/dist/esm/hash.browser.js.map +1 -0
  13. package/dist/esm/hash.node.d.ts +31 -0
  14. package/dist/esm/hash.node.d.ts.map +1 -0
  15. package/dist/esm/hash.node.js +43 -0
  16. package/dist/esm/hash.node.js.map +1 -0
  17. package/dist/esm/hash.test.d.ts +2 -0
  18. package/dist/esm/hash.test.d.ts.map +1 -0
  19. package/dist/esm/hash.test.js +181 -0
  20. package/dist/esm/hash.test.js.map +1 -0
  21. package/dist/esm/index.d.ts +44 -0
  22. package/dist/esm/index.d.ts.map +1 -0
  23. package/dist/esm/index.js +643 -0
  24. package/dist/esm/index.js.map +1 -0
  25. package/dist/esm/index.test.d.ts +2 -0
  26. package/dist/esm/index.test.d.ts.map +1 -0
  27. package/dist/esm/index.test.js +293 -0
  28. package/dist/esm/index.test.js.map +1 -0
  29. package/dist/esm/types.d.ts +149 -0
  30. package/dist/esm/types.d.ts.map +1 -0
  31. package/dist/esm/types.js +2 -0
  32. package/dist/esm/types.js.map +1 -0
  33. package/dist/esm/utils.d.ts +4 -0
  34. package/dist/esm/utils.d.ts.map +1 -0
  35. package/dist/esm/utils.js +23 -0
  36. package/dist/esm/utils.js.map +1 -0
  37. package/dist/esm/v3.d.ts +5 -0
  38. package/dist/esm/v3.d.ts.map +1 -0
  39. package/dist/esm/v3.js +60 -0
  40. package/dist/esm/v3.js.map +1 -0
  41. package/dist/hash.browser.d.ts +1 -0
  42. package/dist/hash.browser.d.ts.map +1 -0
  43. package/dist/hash.browser.js +1 -0
  44. package/dist/hash.browser.js.map +1 -0
  45. package/dist/hash.node.d.ts +1 -0
  46. package/dist/hash.node.d.ts.map +1 -0
  47. package/dist/hash.node.js +1 -0
  48. package/dist/hash.node.js.map +1 -0
  49. package/dist/hash.test.d.ts +2 -0
  50. package/dist/hash.test.d.ts.map +1 -0
  51. package/dist/hash.test.js +183 -0
  52. package/dist/hash.test.js.map +1 -0
  53. package/dist/index.d.ts +1 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +1 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/index.test.d.ts +2 -0
  58. package/dist/index.test.d.ts.map +1 -0
  59. package/dist/index.test.js +295 -0
  60. package/dist/index.test.js.map +1 -0
  61. package/dist/types.d.ts +1 -0
  62. package/dist/types.d.ts.map +1 -0
  63. package/dist/types.js +1 -0
  64. package/dist/types.js.map +1 -0
  65. package/dist/utils.d.ts +1 -0
  66. package/dist/utils.d.ts.map +1 -0
  67. package/dist/utils.js +1 -0
  68. package/dist/utils.js.map +1 -0
  69. package/dist/v3.d.ts +1 -0
  70. package/dist/v3.d.ts.map +1 -0
  71. package/dist/v3.js +1 -0
  72. package/dist/v3.js.map +1 -0
  73. package/package.json +7 -13
  74. package/src/constants.ts +61 -0
  75. package/src/hash.browser.ts +65 -0
  76. package/src/hash.node.ts +47 -0
  77. package/src/hash.test.ts +217 -0
  78. package/src/index.test.ts +378 -0
  79. package/src/index.ts +678 -0
  80. package/src/types.ts +186 -0
  81. package/src/utils.ts +18 -0
  82. package/src/v3.ts +62 -0
@@ -0,0 +1,217 @@
1
+ import { sha256, verify, fromUrlSafeBase64, toUrlSafeBase64 } from './hash.node';
2
+
3
+ describe('Hash utilities', () => {
4
+ describe('sha256', () => {
5
+ it('should hash a simple string', () => {
6
+ const input = 'hello world';
7
+ const hash = sha256(input);
8
+
9
+ // Verify it's URL-safe (no +, /, or =)
10
+ expect(hash).not.toContain('+');
11
+ expect(hash).not.toContain('/');
12
+ expect(hash).not.toContain('=');
13
+
14
+ // Verify consistent output
15
+ const hash2 = sha256(input);
16
+ expect(hash).toBe(hash2);
17
+ });
18
+
19
+ it('should produce correct hash for known input', () => {
20
+ const input = 'hello world';
21
+ const expectedHash = 'uU0nuZNNPgilLlLX2n2r-sSE7-N6U4DukIj3rOLvzek';
22
+ const hash = sha256(input);
23
+ expect(hash).toBe(expectedHash);
24
+ });
25
+
26
+ it('should handle empty string', () => {
27
+ const hash = sha256('');
28
+ expect(hash).toBeTruthy();
29
+ expect(typeof hash).toBe('string');
30
+ });
31
+
32
+ it('should handle unicode characters', () => {
33
+ const input = '你好世界 🌍';
34
+ const hash = sha256(input);
35
+ expect(hash).toBeTruthy();
36
+ expect(typeof hash).toBe('string');
37
+
38
+ // Verify consistency
39
+ const hash2 = sha256(input);
40
+ expect(hash).toBe(hash2);
41
+ });
42
+
43
+ it('should handle Buffer input', () => {
44
+ const data = Buffer.from('hello world');
45
+ const hash = sha256(data);
46
+
47
+ // Should produce same hash as string input
48
+ const stringHash = sha256('hello world');
49
+ expect(hash).toBe(stringHash);
50
+ });
51
+
52
+ it('should produce different hashes for different inputs', () => {
53
+ const hash1 = sha256('hello');
54
+ const hash2 = sha256('world');
55
+ expect(hash1).not.toBe(hash2);
56
+ });
57
+
58
+ it('should produce 43-character URL-safe base64 string', () => {
59
+ const hash = sha256('test');
60
+ // SHA-256 produces 256 bits = 32 bytes
61
+ // Base64 encoding: 32 bytes * 4/3 = 42.67, rounded up = 43 chars (without padding)
62
+ expect(hash.length).toBe(43);
63
+ });
64
+ });
65
+
66
+ describe('verify', () => {
67
+ it('should verify correct hash', () => {
68
+ const content = 'hello world';
69
+ const hash = sha256(content);
70
+ const isValid = verify(content, hash);
71
+ expect(isValid).toBe(true);
72
+ });
73
+
74
+ it('should reject incorrect hash', () => {
75
+ const content = 'hello world';
76
+ const wrongHash = 'incorrect_hash_value_here_1234567890';
77
+ const isValid = verify(content, wrongHash);
78
+ expect(isValid).toBe(false);
79
+ });
80
+
81
+ it('should reject hash for different content', () => {
82
+ const content1 = 'hello world';
83
+ const content2 = 'goodbye world';
84
+ const hash1 = sha256(content1);
85
+ const isValid = verify(content2, hash1);
86
+ expect(isValid).toBe(false);
87
+ });
88
+
89
+ it('should work with Buffer', () => {
90
+ const data = Buffer.from('test data');
91
+ const hash = sha256(data);
92
+ const isValid = verify(data, hash);
93
+ expect(isValid).toBe(true);
94
+ });
95
+ });
96
+
97
+ describe('fromUrlSafeBase64', () => {
98
+ it('should convert URL-safe base64 to standard base64', () => {
99
+ // Use a URL-safe string that contains both - and _ characters
100
+ const urlSafe = 'abc-def_ghi';
101
+ const standard = fromUrlSafeBase64(urlSafe);
102
+
103
+ // Should replace - with + and _ with /
104
+ expect(standard).toContain('+');
105
+ expect(standard).toContain('/');
106
+ // Should add padding
107
+ expect(standard.endsWith('=')).toBe(true);
108
+ });
109
+
110
+ it('should add correct padding', () => {
111
+ // Test different padding scenarios
112
+ const testCases = [
113
+ { input: 'abc', expectedPadding: 1 },
114
+ { input: 'abcd', expectedPadding: 0 },
115
+ { input: 'abcde', expectedPadding: 3 },
116
+ { input: 'abcdef', expectedPadding: 2 },
117
+ ];
118
+
119
+ testCases.forEach(({ input, expectedPadding }) => {
120
+ const result = fromUrlSafeBase64(input);
121
+ const paddingCount = (result.match(/=/g) || []).length;
122
+ expect(paddingCount).toBe(expectedPadding);
123
+ });
124
+ });
125
+
126
+ it('should handle strings without special characters', () => {
127
+ const input = 'abcdefghijklmnop';
128
+ const result = fromUrlSafeBase64(input);
129
+ expect(result).toBeTruthy();
130
+ });
131
+ });
132
+
133
+ describe('toUrlSafeBase64', () => {
134
+ it('should convert standard base64 to URL-safe', () => {
135
+ const standard = 'uU0nuZNNPgilLlLX2n2r+sSE7+N6U4DukIj3rOLvzek=';
136
+ const urlSafe = toUrlSafeBase64(standard);
137
+
138
+ // Should not contain standard base64 special characters
139
+ expect(urlSafe).not.toContain('+');
140
+ expect(urlSafe).not.toContain('/');
141
+ expect(urlSafe).not.toContain('=');
142
+
143
+ // Should contain URL-safe replacements
144
+ expect(urlSafe).toContain('-');
145
+ });
146
+
147
+ it('should remove padding', () => {
148
+ const withPadding = 'abc=';
149
+ const result = toUrlSafeBase64(withPadding);
150
+ expect(result).not.toContain('=');
151
+ expect(result).toBe('abc');
152
+ });
153
+
154
+ it('should be reversible with fromUrlSafeBase64', () => {
155
+ // Start with a standard base64 string with special chars
156
+ const original = 'test+data/with==';
157
+ const urlSafe = toUrlSafeBase64(original);
158
+ const restored = fromUrlSafeBase64(urlSafe);
159
+
160
+ // Should restore to equivalent base64 (padding might differ slightly)
161
+ expect(restored.replace(/=+$/, '')).toBe(original.replace(/=+$/, ''));
162
+ });
163
+ });
164
+
165
+ describe('Round-trip conversions', () => {
166
+ it('should maintain hash integrity through URL-safe conversion', () => {
167
+ const content = 'test content for hashing';
168
+ const hash = sha256(content);
169
+
170
+ // Convert to standard base64 and back
171
+ const standard = fromUrlSafeBase64(hash);
172
+ const backToUrlSafe = toUrlSafeBase64(standard);
173
+
174
+ expect(backToUrlSafe).toBe(hash);
175
+ });
176
+
177
+ it('should verify hash after conversion', () => {
178
+ const content = 'verification test';
179
+ const hash = sha256(content);
180
+
181
+ // Convert and back
182
+ const standard = fromUrlSafeBase64(hash);
183
+ const urlSafe = toUrlSafeBase64(standard);
184
+
185
+ // Should still verify
186
+ const isValid = verify(content, urlSafe);
187
+ expect(isValid).toBe(true);
188
+ });
189
+ });
190
+
191
+ describe('Edge cases', () => {
192
+ it('should handle very long strings', () => {
193
+ const longString = 'a'.repeat(10000);
194
+ const hash = sha256(longString);
195
+ expect(hash).toBeTruthy();
196
+ expect(hash.length).toBe(43);
197
+ });
198
+
199
+ it('should handle special characters', () => {
200
+ const special = '!@#$%^&*()_+-=[]{}|;:,.<>?';
201
+ const hash = sha256(special);
202
+ expect(hash).toBeTruthy();
203
+
204
+ const isValid = verify(special, hash);
205
+ expect(isValid).toBe(true);
206
+ });
207
+
208
+ it('should handle newlines and whitespace', () => {
209
+ const withNewlines = 'line1\nline2\r\nline3\ttab';
210
+ const hash = sha256(withNewlines);
211
+ expect(hash).toBeTruthy();
212
+
213
+ const isValid = verify(withNewlines, hash);
214
+ expect(isValid).toBe(true);
215
+ });
216
+ });
217
+ });
@@ -0,0 +1,378 @@
1
+ import {
2
+ parseRating,
3
+ parseStatement,
4
+ parseOrganisationVerification,
5
+ parsePDFSigning,
6
+ parsePersonVerification,
7
+ parseDisputeAuthenticity,
8
+ parseDisputeContent,
9
+ parseVote,
10
+ parsePoll,
11
+ parseQuotation,
12
+ parseBounty,
13
+ parseBoycott,
14
+ parseObservation,
15
+ parseResponseContent,
16
+ buildResponseContent,
17
+ buildRating,
18
+ buildStatement,
19
+ buildBounty,
20
+ buildDisputeAuthenticityContent,
21
+ buildDisputeContentContent,
22
+ buildPDFSigningContent,
23
+ buildPersonVerificationContent,
24
+ buildPollContent,
25
+ buildQuotationContent,
26
+ buildVoteContent,
27
+ buildOrganisationVerificationContent,
28
+ buildBoycott,
29
+ buildObservation,
30
+ } from './index'
31
+
32
+ const randomUnicodeString = () =>
33
+ Array.from({ length: 20 }, () =>
34
+ String.fromCharCode(Math.floor(Math.random() * 65536))
35
+ )
36
+ .join('')
37
+ .replace(/[\n;>=<"''\\]/g, '')
38
+
39
+ test('parse statement', () => {
40
+ const statement = `Publishing domain: localhost
41
+ Author: chris
42
+ Time: Tue, 18 Apr 2023 18:20:26 GMT
43
+ Tags: hashtag1, hashtag2
44
+ Format version: 4
45
+ Statement content: hi
46
+ `
47
+ const parsedStatement = parseStatement({ statement })
48
+ expect(parsedStatement.content).toBe(`hi
49
+ `)
50
+ })
51
+
52
+ test('statement build & parse function compatibility: input=parse(build(input))', () => {
53
+ const [domain, author, representative, content, supersededStatement] =
54
+ Array.from({ length: 5 }, randomUnicodeString)
55
+ const tags = Array.from({ length: 4 }, randomUnicodeString)
56
+ const contentWithTrailingNewline =
57
+ content + (content.match(/\n$/) ? '' : '\n')
58
+ const time = new Date('Sun, 04 Sep 2022 14:48:50 GMT')
59
+ const statementContent = buildStatement({
60
+ domain,
61
+ author,
62
+ time,
63
+ content: contentWithTrailingNewline,
64
+ representative,
65
+ supersededStatement,
66
+ tags,
67
+ })
68
+ const parsedStatement = parseStatement({ statement: statementContent })
69
+ expect(parsedStatement.domain).toBe(domain)
70
+ expect(parsedStatement.author).toBe(author)
71
+ expect(parsedStatement.time?.toUTCString()).toBe(time.toUTCString())
72
+ expect(parsedStatement.content).toBe(contentWithTrailingNewline)
73
+ expect(parsedStatement.representative).toBe(representative)
74
+ expect(parsedStatement.supersededStatement).toBe(supersededStatement)
75
+ expect(parsedStatement.tags?.sort()).toStrictEqual(tags.sort())
76
+ })
77
+
78
+ test('parse quotation', () => {
79
+ let quotation = `Publishing domain: rixdata.net
80
+ Author: Example Inc.
81
+ Time: Sun, 04 Sep 2022 14:48:50 GMT
82
+ Format version: 4
83
+ Statement content:
84
+ Type: Quotation
85
+ Original author: XYZ Company Inc.
86
+ Author verification: eXoVsm2CdF5Ri-SEAr33RNkG3DBuehvFoDBQ_pO9CXE
87
+ Original publication time: Sun, 04 Sep 2022 14:48:50 GMT
88
+ Source: https://www.facebook.com/companyxzy/posts/XXXX
89
+ Picture proof: 5HKiyQXGV4xavq-Nn9RXi_ndUH-2BEux3ccFIjaSk_8
90
+ Confidence: 0.9
91
+ Quotation: we give example.com a 2/5 star rating
92
+ Paraphrased statement:
93
+ Type: Rating
94
+ Organisation name: example
95
+ Organisation domain: example.com
96
+ Our rating: 2/5 Stars
97
+ `
98
+ const parsedStatement = parseStatement({ statement: quotation })
99
+ const parsedQuotation = parseQuotation(parsedStatement.content)
100
+ const type = parsedQuotation.type
101
+ expect(type).toBe('rating')
102
+ })
103
+
104
+ test('quotation build & parse function compatibility: input=parse(build(input))', () => {
105
+ const [originalAuthor, source, picture, quotation, paraphrasedStatement] =
106
+ Array.from({ length: 6 }, randomUnicodeString)
107
+ const authorVerification = 'yXoVsm2CdF5Ri-SEAr33RNkG3DBuehvFoDBQ_pO9CXE'
108
+ const originalTime = 'Sun, 04 Sep 2022 14:48:50 GMT'
109
+ const confidence = '' + Math.random()
110
+ const quotationContent = buildQuotationContent({
111
+ originalAuthor,
112
+ authorVerification,
113
+ originalTime,
114
+ source,
115
+ picture,
116
+ confidence,
117
+ quotation,
118
+ paraphrasedStatement,
119
+ })
120
+ const parsedQuotation = parseQuotation(quotationContent)
121
+ expect(parsedQuotation.originalAuthor).toBe(originalAuthor)
122
+ expect(parsedQuotation.originalTime).toBe(originalTime)
123
+ expect(parsedQuotation.source).toBe(source)
124
+ expect(parsedQuotation.picture).toBe(picture)
125
+ expect(parsedQuotation.confidence).toBe(confidence)
126
+ expect(parsedQuotation.quotation).toBe(quotation)
127
+ expect(parsedQuotation.paraphrasedStatement?.replace(/\n$/, '')).toBe(
128
+ paraphrasedStatement
129
+ )
130
+ expect(parsedQuotation.authorVerification).toBe(authorVerification)
131
+ })
132
+
133
+ test('parse organisation verification', () => {
134
+ let organisationVerification = `Publishing domain: rixdata.net
135
+ Author: Example Inc.
136
+ Time: Sun, 04 Sep 2022 14:48:50 GMT
137
+ Format version: 4
138
+ Statement content:
139
+ Type: Organisation verification
140
+ Description: We verified the following information about an organisation.
141
+ Name: Walmart Inc.
142
+ Country: United States of America
143
+ Legal entity: corporation
144
+ Owner of the domain: walmart.com
145
+ Province or state: Arkansas
146
+ City: Bentonville
147
+ `
148
+ const parsedStatement = parseStatement({
149
+ statement: organisationVerification,
150
+ })
151
+ const parsedOVerification = parseOrganisationVerification(
152
+ parsedStatement.content
153
+ )
154
+ const name = parsedOVerification.name
155
+ expect(name).toBe('Walmart Inc.')
156
+ })
157
+
158
+ test('organisation verification build & parse function compatibility: input=parse(build(input))', () => {
159
+ const [
160
+ name,
161
+ englishName,
162
+ city,
163
+ domain,
164
+ foreignDomain,
165
+ serialNumber,
166
+ reliabilityPolicy,
167
+ pictureHash,
168
+ ] = Array.from({ length: 8 }, randomUnicodeString)
169
+ const country = 'Germany'
170
+ const province = 'Bayern'
171
+ const legalForm = 'corporation'
172
+ const employeeCount = '100-1000'
173
+ const confidence = 0.8
174
+ const verificationContent = buildOrganisationVerificationContent({
175
+ name,
176
+ englishName,
177
+ country,
178
+ city,
179
+ province,
180
+ legalForm,
181
+ domain,
182
+ pictureHash,
183
+ foreignDomain,
184
+ serialNumber,
185
+ confidence,
186
+ reliabilityPolicy,
187
+ employeeCount,
188
+ })
189
+ const parsedVerification =
190
+ parseOrganisationVerification(verificationContent)
191
+ expect(parsedVerification.name).toBe(name)
192
+ expect(parsedVerification.englishName).toBe(englishName)
193
+ expect(parsedVerification.country).toBe(country)
194
+ expect(parsedVerification.city).toBe(city)
195
+ expect(parsedVerification.province).toBe(province)
196
+ expect(parsedVerification.legalForm).toBe(legalForm)
197
+ expect(parsedVerification.domain).toBe(domain)
198
+ expect(parsedVerification.foreignDomain).toBe(foreignDomain)
199
+ expect(parsedVerification.serialNumber).toBe(serialNumber)
200
+ expect(parsedVerification.confidence).toBe(confidence)
201
+ expect(parsedVerification.pictureHash).toBe(pictureHash)
202
+ expect(parsedVerification.reliabilityPolicy).toBe(reliabilityPolicy)
203
+ expect(parsedVerification.employeeCount).toBe(employeeCount)
204
+ })
205
+
206
+ test('parse person verification', () => {
207
+ let personVerification = `Publishing domain: rixdata.net
208
+ Author: Example Inc.
209
+ Time: Sun, 04 Sep 2022 14:48:50 GMT
210
+ Format version: 4
211
+ Statement content:
212
+ Type: Person verification
213
+ Description: We verified the following information about a person.
214
+ Name: Barack Hossein Obama II
215
+ Date of birth: 4 Aug 1961
216
+ City of birth: Honolulu
217
+ Country of birth: United States of America
218
+ Owner of the domain: barackobama.com
219
+ `
220
+ const parsedStatement = parseStatement({ statement: personVerification })
221
+ const parsedPVerification = parsePersonVerification(parsedStatement.content)
222
+ const name = parsedPVerification.name
223
+ expect(name).toBe('Barack Hossein Obama II')
224
+ })
225
+
226
+ test('person verification build & parse function compatibility: input=parse(build(input))', () => {
227
+ const [
228
+ name,
229
+ ownDomain,
230
+ foreignDomain,
231
+ jobTitle,
232
+ employer,
233
+ verificationMethod,
234
+ picture,
235
+ reliabilityPolicy,
236
+ ] = Array.from({ length: 12 }, randomUnicodeString)
237
+ const countryOfBirth = 'Germany'
238
+ const cityOfBirth = 'Berlin'
239
+ const confidence = Math.random()
240
+ const dateOfBirth = new Date(0)
241
+ const personVerificationContent = buildPersonVerificationContent({
242
+ name,
243
+ countryOfBirth,
244
+ cityOfBirth,
245
+ ownDomain,
246
+ foreignDomain,
247
+ dateOfBirth,
248
+ jobTitle,
249
+ employer,
250
+ verificationMethod,
251
+ confidence,
252
+ picture,
253
+ reliabilityPolicy,
254
+ })
255
+
256
+ const parsedVerification = parsePersonVerification(
257
+ personVerificationContent
258
+ )
259
+ expect(parsedVerification.name).toBe(name)
260
+ expect(parsedVerification.ownDomain).toBe(ownDomain)
261
+ expect(parsedVerification.foreignDomain).toBe(foreignDomain)
262
+ expect(parsedVerification.dateOfBirth.toUTCString()).toBe(
263
+ dateOfBirth.toUTCString()
264
+ )
265
+ expect(parsedVerification.jobTitle).toBe(jobTitle)
266
+ expect(parsedVerification.employer).toBe(employer)
267
+ expect(parsedVerification.verificationMethod).toBe(verificationMethod)
268
+ expect(parsedVerification.confidence).toBe(confidence)
269
+ expect(parsedVerification.picture).toBe(picture)
270
+ expect(parsedVerification.reliabilityPolicy).toBe(reliabilityPolicy)
271
+ expect(parsedVerification.countryOfBirth).toBe(countryOfBirth)
272
+ expect(parsedVerification.cityOfBirth).toBe(cityOfBirth)
273
+ })
274
+
275
+ test('parse rating', () => {
276
+ let rating = `Publishing domain: localhost
277
+ Author: chris
278
+ Time: Tue, 18 Apr 2023 18:20:26 GMT
279
+ Format version: 4
280
+ Statement content:
281
+ Type: Rating
282
+ Subject name: AMBOSS GmbH
283
+ URL that identifies the subject: amboss.com
284
+ Rated quality: AI safety
285
+ Our rating: 5/5 Stars
286
+ `
287
+ const parsedStatement = parseStatement({ statement: rating })
288
+ const parsedRating = parseRating(parsedStatement.content)
289
+ const ratingNumber = parsedRating.rating
290
+ expect(ratingNumber).toBe(5)
291
+ const subjectName = parsedRating.subjectName
292
+ expect(subjectName).toBe('AMBOSS GmbH')
293
+ const subjectReference = parsedRating.subjectReference
294
+ expect(subjectReference).toBe('amboss.com')
295
+ const quality = parsedRating.quality
296
+ expect(quality).toBe('AI safety')
297
+ })
298
+
299
+ test('rating build & parse function compatibility: input=parse(build(input))', () => {
300
+ const [subjectName, subjectReference, comment, quality] = Array.from(
301
+ { length: 4 },
302
+ randomUnicodeString
303
+ )
304
+ const rating = Math.ceil(Math.random() * 5)
305
+ const ratingContent = buildRating({ subjectName, subjectReference, rating, comment, quality })
306
+ const parsedRating = parseRating(ratingContent)
307
+ expect(parsedRating.subjectName).toBe(subjectName)
308
+ expect(parsedRating.subjectReference).toBe(subjectReference)
309
+ expect(parsedRating.quality).toBe(quality)
310
+ expect(parsedRating.rating).toBe(rating)
311
+ expect(parsedRating.comment).toBe(comment)
312
+ })
313
+
314
+ test('parse poll v4', () => {
315
+ let poll = `Publishing domain: rixdata.net
316
+ Author: Example Inc.
317
+ Time: Thu, 17 Nov 2022 13:38:20 GMT
318
+ Format version: 4
319
+ Statement content:
320
+ Type: Poll
321
+ The poll outcome is finalized when the following nodes agree: rixdata.net
322
+ Voting deadline: Thu, 01 Dec 2022 13:38:26 GMT
323
+ Poll: Should the UK join the EU
324
+ Option 1: Yes
325
+ Option 2: No
326
+ Who can vote:
327
+ Description: All universities with a ROR ID
328
+ Legal form scope: corporation
329
+ All entities with the following property: ROR ID
330
+ As observed by: Rix Data NL B.V.@rixdata.net
331
+ Link to query defining who can vote: https://stated.rixdata.net/?search_query=%09Observed%20property:%20ROR%20ID%0A%09&domain=rixdata.net&author=Rix%20Data%20NL%20B.V.
332
+ `
333
+ const parsedStatement = parseStatement({ statement: poll })
334
+ const parsedPoll = parsePoll(parsedStatement.content)
335
+ const pollTitle = parsedPoll.poll
336
+ expect(pollTitle).toBe('Should the UK join the EU')
337
+ expect(parsedPoll.options[0]).toBe('Yes')
338
+ expect(parsedPoll.options[1]).toBe('No')
339
+ expect(parsedPoll.deadline?.toUTCString()).toBe(
340
+ 'Thu, 01 Dec 2022 13:38:26 GMT'
341
+ )
342
+ expect(parsedPoll.scopeDescription).toBe('All universities with a ROR ID')
343
+ expect(parsedPoll.legalEntity).toBe('corporation')
344
+ expect(parsedPoll.requiredProperty).toBe('ROR ID')
345
+ expect(parsedPoll.requiredPropertyObserver).toBe(
346
+ 'Rix Data NL B.V.@rixdata.net'
347
+ )
348
+ expect(parsedPoll.scopeQueryLink).toBe(
349
+ 'https://stated.rixdata.net/?search_query=%09Observed%20property:%20ROR%20ID%0A%09&domain=rixdata.net&author=Rix%20Data%20NL%20B.V.'
350
+ )
351
+ })
352
+
353
+ test('poll build & parse function compatibility: input=parse(build(input))', () => {
354
+ const [country, city, legalEntity, judges, poll, scopeDescription] =
355
+ Array.from({ length: 6 }, randomUnicodeString)
356
+ const options = Array.from({ length: 2 }, randomUnicodeString)
357
+ const domainScope = ['rixdata.net']
358
+ const deadline = new Date('Thu, 01 Dec 2022 13:38:26 GMT')
359
+ const pollContent = buildPollContent({
360
+ country,
361
+ city,
362
+ legalEntity,
363
+ domainScope,
364
+ judges,
365
+ deadline,
366
+ poll,
367
+ options,
368
+ scopeDescription,
369
+ })
370
+ const parsedPoll = parsePoll(pollContent)
371
+ expect(parsedPoll.poll).toBe(poll)
372
+ expect(parsedPoll.country).toBe(country)
373
+ expect(parsedPoll.legalEntity).toBe(legalEntity)
374
+ expect(parsedPoll.judges).toBe(judges)
375
+ expect(parsedPoll.deadline?.toUTCString()).toBe(deadline.toUTCString())
376
+ expect(parsedPoll.options[0]).toEqual(options[0])
377
+ expect(parsedPoll.options[1]).toEqual(options[1])
378
+ })