Files: 7b830c35a60fe8e303f9e2f3a156a6f3516a8cb1 / test / position / sync / buildResults.test.js
6573 bytesRaw
1 | const test = require('tape') |
2 | const pull = require('pull-stream') |
3 | const ChooseOne = require('../../../position/async/buildChooseOne')() |
4 | const ChooseOnePoll = require('../../../poll/sync/buildChooseOne') |
5 | const chooseOneResults = require('../../../position/sync/buildResults') |
6 | const {isPosition, isPoll} = require('ssb-poll-schema') |
7 | const {ERROR_POSITION_CHOICE, ERROR_POSITION_LATE} = require('../../../types') |
8 | |
9 | const pietId = '@Mq8D3YC6VdErKQzV3oi2oK5hHSoIwR0hUQr4M46wr/0=.ed25519' |
10 | const mixId = '@Mq8D3YC6VdErKQzV3oi2oK5hHSoIwR0hUQr4M46wr/1=.ed25519' |
11 | const mikeyId = '@Mq8D3YC6VdErKQzV3oi2oK5hHSoIwR0hUQr4M46wr/2=.ed25519' |
12 | const timmyId = '@Mq8D3YC6VdErKQzV3oi2oK5hHSoIwR0hUQr4M46wr/3=.ed25519' |
13 | const tommyId = '@Mq8D3YC6VdErKQzV3oi2oK5hHSoIwR0hUQr4M46wr/4=.ed25519' |
14 | const sallyId = '@Mq8D3YC6VdErKQzV3oi2oK5hHSoIwR0hUQr4M46wr/5=.ed25519' |
15 | |
16 | const poll = '%t+PhrNxxXkw/jMo6mnwUWfFjJapoPWxzsQoe0Np+nYw=.sha256' |
17 | |
18 | const now = new Date().toISOString() |
19 | |
20 | const validPoll = { |
21 | key: '%t+PhrNxxXkw/jMo6mnwUWfFjJapoPWxzsQoe0Np+nYw=.sha256', |
22 | value: { |
23 | content: ChooseOnePoll({ |
24 | choices: [1, 2, 'three'], |
25 | title: 'how many food', |
26 | closesAt: now |
27 | }) |
28 | } |
29 | } |
30 | |
31 | test('ChooseOneResults - ChooseOneResults', function (t) { |
32 | const positions = [ |
33 | { value: { content: {choice: 0, poll}, author: pietId } }, |
34 | { value: { content: {choice: 0, poll}, author: mixId } }, |
35 | { value: { content: {choice: 0, poll}, author: mikeyId } }, |
36 | { value: { content: {choice: 1, poll}, author: timmyId } }, |
37 | { value: { content: {choice: 1, poll}, author: tommyId } }, |
38 | { value: { content: {choice: 2, poll}, author: sallyId } } |
39 | ] |
40 | |
41 | const expected = { |
42 | results: [ |
43 | { |
44 | choice: 1, |
45 | voters: { |
46 | [pietId]: positions[0], |
47 | [mixId]: positions[1], |
48 | [mikeyId]: positions[2] |
49 | } |
50 | }, |
51 | { |
52 | choice: 2, |
53 | voters: { |
54 | [timmyId]: positions[3], |
55 | [tommyId]: positions[4] |
56 | } |
57 | }, |
58 | { |
59 | choice: 'three', |
60 | voters: { |
61 | [sallyId]: positions[5] |
62 | } |
63 | } |
64 | ], |
65 | errors: {} |
66 | } |
67 | |
68 | pull( |
69 | pull.values(positions), |
70 | pull.asyncMap((fullPosition, cb) => { |
71 | ChooseOne(fullPosition.value.content, (err, position) => { |
72 | fullPosition.value.content = position |
73 | cb(err, fullPosition) |
74 | }) |
75 | }), |
76 | pull.collect(postions => { |
77 | const actual = chooseOneResults({positions, poll: validPoll}) |
78 | t.deepEqual(actual, expected, 'results are correct') |
79 | t.end() |
80 | }) |
81 | ) |
82 | }) |
83 | |
84 | test('ChooseOneResults - a position stated for an invalid choice index is not counted', function (t) { |
85 | const positions = [ |
86 | { value: { content: {choice: 3, poll}, author: pietId } } |
87 | ] |
88 | |
89 | pull( |
90 | pull.values(positions), |
91 | pull.asyncMap((fullPosition, cb) => { |
92 | ChooseOne(fullPosition.value.content, (err, position) => { |
93 | fullPosition.value.content = position |
94 | cb(err, fullPosition) |
95 | }) |
96 | }), |
97 | pull.collect(postions => { |
98 | const actual = chooseOneResults({positions, poll: validPoll}) |
99 | t.false(actual.results[3], 'invalid vote is not counted') |
100 | t.end() |
101 | }) |
102 | ) |
103 | }) |
104 | |
105 | test('ChooseOneResults - a position stated for an invalid choice index is included in the errors object', function (t) { |
106 | const positions = [ |
107 | { value: { content: {choice: 3, poll}, author: pietId } } |
108 | ] |
109 | |
110 | pull( |
111 | pull.values(positions), |
112 | pull.asyncMap((fullPosition, cb) => { |
113 | ChooseOne(fullPosition.value.content, (err, position) => { |
114 | fullPosition.value.content = position |
115 | cb(err, fullPosition) |
116 | }) |
117 | }), |
118 | pull.collect(postions => { |
119 | const actual = chooseOneResults({positions, poll: validPoll}) |
120 | t.deepEqual(actual.errors[0].type, ERROR_POSITION_CHOICE, 'invalid vote is on error object') |
121 | t.end() |
122 | }) |
123 | ) |
124 | }) |
125 | |
126 | test('ChooseOneResults - A position stated before the closing time of the poll is counted', function (t) { |
127 | const positions = [ |
128 | { value: { content: {choice: 0, poll}, author: pietId, timestamp: now - 1 } } |
129 | ] |
130 | |
131 | pull( |
132 | pull.values(positions), |
133 | pull.asyncMap((fullPosition, cb) => { |
134 | ChooseOne(fullPosition.value.content, (err, position) => { |
135 | fullPosition.value.content = position |
136 | cb(err, fullPosition) |
137 | }) |
138 | }), |
139 | pull.collect(postions => { |
140 | const actual = chooseOneResults({positions, poll: validPoll}) |
141 | t.ok(actual.results[0].voters[pietId], 'valid vote is counted') |
142 | t.end() |
143 | }) |
144 | ) |
145 | }) |
146 | |
147 | test('ChooseOneResults - A position stated after the closing time of the poll is not counted', function (t) { |
148 | const positions = [ |
149 | { value: { content: {choice: 0, poll}, author: pietId, timestamp: now + 1 } } |
150 | ] |
151 | |
152 | pull( |
153 | pull.values(positions), |
154 | pull.asyncMap((fullPosition, cb) => { |
155 | ChooseOne(fullPosition.value.content, (err, position) => { |
156 | fullPosition.value.content = position |
157 | cb(err, fullPosition) |
158 | }) |
159 | }), |
160 | pull.collect(postions => { |
161 | const actual = chooseOneResults({positions, poll: validPoll}) |
162 | t.deepEqual(actual.results[0].voters, {}, 'invalid vote is not counted') |
163 | t.end() |
164 | }) |
165 | ) |
166 | }) |
167 | |
168 | test('ChooseOneResults - A position stated after the closing time of the poll is included in the error object', function (t) { |
169 | const positions = [ |
170 | { value: { content: {choice: 0, poll}, author: pietId, timestamp: now + 1 } } |
171 | ] |
172 | |
173 | pull( |
174 | pull.values(positions), |
175 | pull.asyncMap((fullPosition, cb) => { |
176 | ChooseOne(fullPosition.value.content, (err, position) => { |
177 | fullPosition.value.content = position |
178 | cb(err, fullPosition) |
179 | }) |
180 | }), |
181 | pull.collect(postions => { |
182 | const actual = chooseOneResults({positions, poll: validPoll}) |
183 | t.deepEqual(actual.errors[0].type, ERROR_POSITION_LATE, 'invalid vote is on error object') |
184 | t.end() |
185 | }) |
186 | ) |
187 | }) |
188 | |
189 | test('ChooseOneResults - ChooseOneResults only counts latest vote by an author', function (t) { |
190 | const positions = [ |
191 | { value: { content: {choice: 2, poll}, author: pietId } }, |
192 | { value: { content: {choice: 0, poll}, author: pietId } } |
193 | ] |
194 | |
195 | pull( |
196 | pull.values(positions), |
197 | pull.asyncMap((fullPosition, cb) => { |
198 | ChooseOne(fullPosition.value.content, (err, position) => { |
199 | fullPosition.value.content = position |
200 | cb(err, fullPosition) |
201 | }) |
202 | }), |
203 | pull.collect(postions => { |
204 | const actual = chooseOneResults({positions, poll: validPoll}) |
205 | t.false(actual.results[2].voters[pietId], 'old vote is deleted') |
206 | t.true(actual.results[0].voters[pietId], 'new vote is counted') |
207 | t.end() |
208 | }) |
209 | ) |
210 | }) |
211 |
Built with git-ssb-web