suidouble 0.0.10 → 0.0.12

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.
@@ -21,6 +21,24 @@ class SuiPaginatedResponse extends SuiCommonMethods {
21
21
  this._data = [];
22
22
  }
23
23
 
24
+ /**
25
+ * Simple itterator to go over all list of items, not caring about pagination/cursors etc. It fetches next page when needed
26
+ * Optional maxLimit second parameter to stop when reached count
27
+ * @param {Function taking single argument of item} callbackFunc
28
+ * @param {Number} maxLimit
29
+ */
30
+ async forEach(callbackFunc, maxLimit = null) {
31
+ let curN = 0;
32
+ do {
33
+ for (const item of this._data) {
34
+ if (!maxLimit || curN < maxLimit) {
35
+ await callbackFunc(item);
36
+ }
37
+ curN++;
38
+ }
39
+ } while( (!maxLimit || curN < maxLimit) && (await this.nextPage()) );
40
+ }
41
+
24
42
  get hasNextPage() {
25
43
  return this._hasNextPage;
26
44
  }
@@ -21,6 +21,10 @@ class SuiTestScenario extends SuiCommonMethods {
21
21
  this._publishedPackageId = null;
22
22
  }
23
23
 
24
+ get currentAs() {
25
+ return this._currentAs;
26
+ }
27
+
24
28
  /**
25
29
  * Start local test validator and set up `as` as owner of package deploy transaction.
26
30
  * Package will be deployed with method `init`, as we try to mimic Sui Move's test_scenario
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "suidouble",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "Set of provider, package and object classes for javascript representation of Sui Move smart contracts. Use same code for publishing, upgrading, integration testing, interaction with smart contracts and integration in browser web3 dapps",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -211,6 +211,42 @@ test('execute contract methods', async t => {
211
211
  t.equal(responseText, 'ขอบคุณครับ, 🇺🇦');
212
212
  });
213
213
 
214
+ test('testing paginatedResponse', async t => {
215
+ const chatTopMessage = contract.objectStorage.findMostRecentByTypeName('ChatTopMessage');
216
+ t.ok(chatTopMessage);
217
+
218
+ // fill method create a lot of responses ( check out contract's code )
219
+ const moveCallResult = await contract.moveCall('suidouble_chat', 'fill', [chatTopMessage.id, 'the message response', 'metadata']);
220
+ t.ok(moveCallResult.created.length >= 60); // it's 60 in move code, but let's keep chat flexible
221
+
222
+ const eventsResponse = await contract.fetchEvents('suidouble_chat');
223
+ const idsInEventsDict = {};
224
+ let responsesInEventsCount = 0;
225
+ do {
226
+ for (const event of eventsResponse.data) {
227
+ if (!idsInEventsDict[event.parsedJson.id]) {
228
+ idsInEventsDict[event.parsedJson.id] = true;
229
+ responsesInEventsCount++;
230
+ }
231
+ }
232
+ } while(await eventsResponse.nextPage());
233
+
234
+ t.ok(responsesInEventsCount >= 60); // it's 60 in move code, but let's keep chat flexible
235
+
236
+ // or using SuiPaginatedResponse forEach itterator:
237
+ const anotherEventsResponse = await contract.fetchEvents('suidouble_chat');
238
+ let loopsInForEach = 0;
239
+ const idsInLoopDict = {};
240
+ await anotherEventsResponse.forEach(async (event)=>{
241
+ if (!idsInLoopDict[event.parsedJson.id]) {
242
+ idsInLoopDict[event.parsedJson.id] = true;
243
+ loopsInForEach++;
244
+ }
245
+ });
246
+
247
+ t.ok(loopsInForEach >= 60); // it's 60 in move code, but let's keep chat flexible
248
+ });
249
+
214
250
  test('stops local test node', async t => {
215
251
  SuiLocalTestValidator.stop();
216
252
  });
@@ -0,0 +1,57 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap');
4
+ const { test } = t;
5
+ const path = require('path');
6
+
7
+ const { SuiTestScenario } = require('..');
8
+
9
+ let testScenario = null;
10
+
11
+ test('initialization', async t => {
12
+ testScenario = new SuiTestScenario({
13
+ path: path.join(__dirname, './test_move_contracts/suidouble_chat/'),
14
+ debug: false,
15
+ });
16
+
17
+ await testScenario.begin('admin');
18
+ await testScenario.init();
19
+
20
+ t.equal(testScenario.currentAs, 'admin');
21
+ });
22
+
23
+ test('checking takeShared', async t => {
24
+ t.plan(4);
25
+
26
+ await testScenario.nextTx('admin', async()=>{
27
+ const chatShop = testScenario.takeShared('ChatShop');
28
+
29
+ t.ok(chatShop.address); // there should be some address
30
+ t.ok(`${chatShop.address}`.indexOf('0x') === 0); // adress is string starting with '0x'
31
+
32
+ await testScenario.moveCall('suidouble_chat', 'post', [chatShop.address, 'posting a message', 'metadata']);
33
+ const chatTopMessage = testScenario.takeShared('ChatTopMessage');
34
+
35
+ t.ok(chatTopMessage.address); // there should be some address
36
+ t.ok(`${chatTopMessage.address}`.indexOf('0x') === 0); // adress is string starting with '0x'
37
+ });
38
+ });
39
+
40
+ test('checking takeOwned', async t => {
41
+ t.plan(3);
42
+
43
+ await testScenario.nextTx('somebody', async()=>{
44
+ const chatTopMessage = testScenario.takeShared('ChatTopMessage');
45
+ t.ok(chatTopMessage.address); // there should be some address
46
+
47
+ await testScenario.moveCall('suidouble_chat', 'reply', [chatTopMessage.address, 'posting a response', 'metadata']);
48
+ const chatResponse = testScenario.takeFromSender('ChatResponse');
49
+
50
+ t.ok(chatResponse.address); // there should be some address
51
+ t.ok(`${chatResponse.address}`.indexOf('0x') === 0); // adress is string starting with '0x'
52
+ });
53
+ })
54
+
55
+ test('finishing the test scenario', async t => {
56
+ await testScenario.end();
57
+ });
@@ -80,7 +80,7 @@ module suidouble_chat::suidouble_chat {
80
80
  // chat_response.text
81
81
  // }
82
82
 
83
- /// Mint (post) a chatMessage object without referencing another object.
83
+ /// Mint (post) a ChatTopMessage object without referencing another object.
84
84
  public entry fun post(
85
85
  chat_shop: &ChatShop,
86
86
  text: vector<u8>,
@@ -115,6 +115,7 @@ module suidouble_chat::suidouble_chat {
115
115
  transfer::share_object(chat_top_message);
116
116
  }
117
117
 
118
+ /// Mint (post) a ChatResponse object
118
119
  public entry fun reply(
119
120
  chat_top_message: &mut ChatTopMessage,
120
121
  text: vector<u8>,
@@ -147,6 +148,40 @@ module suidouble_chat::suidouble_chat {
147
148
  transfer::transfer(chat_response, tx_context::sender(ctx));
148
149
  }
149
150
 
151
+ /// Mint a lot of responses (we need this to unit test SuiPaginatedResponse faster)
152
+ public entry fun fill(
153
+ chat_top_message: &mut ChatTopMessage,
154
+ text: vector<u8>,
155
+ metadata: vector<u8>,
156
+ ctx: &mut TxContext,
157
+ ) {
158
+ assert!(length(&text) <= MAX_TEXT_LENGTH, ETextOverflow);
159
+
160
+ let dynamic_field_exists = dynamic_object_field::exists_(&chat_top_message.id, b"as_chat_response");
161
+ if (dynamic_field_exists) {
162
+ let top_level_chat_response = dynamic_object_field::remove<vector<u8>, ChatResponse>(&mut chat_top_message.id, b"as_chat_response");
163
+ transfer::transfer(top_level_chat_response, chat_top_message.author);
164
+ };
165
+
166
+ let i: u64 = 0;
167
+
168
+ while (i < 60) {
169
+ let id = object::new(ctx);
170
+
171
+ emit(ChatResponseCreated { id: object::uid_to_inner(&id), top_message_id: object::uid_to_inner(&chat_top_message.id), seq_n: chat_top_message.responses_count });
172
+
173
+ let chat_response = ChatResponse {
174
+ id: id,
175
+ chat_top_message_id: object::id(chat_top_message),
176
+ author: tx_context::sender(ctx),
177
+ text: text,
178
+ metadata,
179
+ seq_n: chat_top_message.responses_count,
180
+ };
181
+ transfer::transfer(chat_response, tx_context::sender(ctx));
182
+ i = i + 1;
183
+ };
184
+ }
150
185
 
151
186
 
152
187
  #[test]