-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit bf49ba7
Showing
35 changed files
with
8,326 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
root = true | ||
|
||
[*] | ||
indent_style = space | ||
indent_size = 2 | ||
end_of_line = lf | ||
charset = utf-8 | ||
insert_final_newline = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
build/ | ||
dist/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "./node_modules/gts/" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
node_modules/ | ||
build/ | ||
dist/ | ||
example.mts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
node_modules/ | ||
build/ | ||
dist/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = { | ||
...require('gts/.prettierrc.json'), | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
# ADAMANT Botfactory E2E | ||
|
||
`botfactory-e2e` is an independent testing framework for [adamant-botfactory](https://github.com/adamant-im/adamant-botfactory) that uses [Fluent interface](https://en.wikipedia.org/wiki/Fluent_interface). | ||
|
||
## Installation | ||
|
||
To use this framework, you would need to install `botfactory-e2e` via your favorite package manager, e.g. `npm`: | ||
|
||
```js | ||
npm install botfactory-e2e | ||
``` | ||
|
||
For a better experience, you may also want to install another testing framework. This documentation uses [`Jest`](https://github.com/jestjs/jest) in its examples, but you can use any other testing framework you prefer. | ||
|
||
## Getting Started | ||
|
||
Let's get started by writing a test for a hypothetical bot that greetings a user. First, create a `bot.js` file: | ||
|
||
```js | ||
import {createBot} from 'adamant-botfactory'; | ||
|
||
const bot = createBot(process.env.PASSPHRASE, { | ||
nodes: [ | ||
/* ... */ | ||
], | ||
}); | ||
|
||
bot.command('start', usr => usr.reply(`Hello, ${usr.address}!`)); | ||
|
||
export {bot}; | ||
``` | ||
|
||
As you can see, we don't start the bot in the same file as we create it because it would interfere with our tests. You might want to create a separate file named `start.js` to run the bot. | ||
|
||
Then, create a file named `bot.test.js`. This will contain our actual test: | ||
|
||
```js | ||
import {createTestBot, createMockNode} from 'botfactory-e2e'; | ||
import {bot} from './bot.js'; | ||
|
||
const node = createMockNode('my-test-node'); | ||
|
||
describe('Greeting Bot', () => { | ||
const testBot = createTestBot(bot, {node}); | ||
|
||
it('should greet a user with the correct address', done => { | ||
const passphrase = | ||
'angry special raise embark animal you ball million bronze science crater review'; | ||
const user = createFakeUser(passphrase); | ||
|
||
user | ||
.interactsWith(testBot) | ||
.sends({command: 'start'}) | ||
.shouldReceive(({message}) => | ||
expect(message.text).toBe('Hello, U14581577999389437648!') | ||
) | ||
.then(done); | ||
}); | ||
}); | ||
|
||
afterAll(() => { | ||
node.shutdown(); | ||
}); | ||
``` | ||
|
||
There's much going on, so let's break this test down line by line. Firstly, we need to create a fake node: | ||
|
||
```js | ||
const node = createMockNode('my-test-node'); | ||
``` | ||
|
||
This will start a local server to fake an ADAMANT node with mock responses. We must pass a unique id for the fake node to separate it from others and allow for future reuse. | ||
|
||
Next, we create a test bot: | ||
|
||
```js | ||
const testBot = createTestBot(bot, {node}); | ||
``` | ||
|
||
What it does is simply make a copy of the bot with a mock passphrase and connect it to the fake node we created earlier. | ||
|
||
Finally, we can create an interface to test the bot using mock user: | ||
|
||
```js | ||
const user = createFakeUser(passphrase); | ||
``` | ||
|
||
Now, as we ready, we can tell the mock user which bot it should interact with: | ||
|
||
```js | ||
user.interactsWith(testBot); | ||
``` | ||
|
||
Then, we are going to test `start` command, so we generate and send a mock message to the bot with the `/start` command: | ||
|
||
```js | ||
user.sends({command: 'start'}); | ||
``` | ||
|
||
To test the bot's response, we can use Jest's built-in assertion function inside the `shouldReceive` method's callback. First argument of the callback is the next transaction our bot will send to the user: | ||
|
||
```js | ||
user.shouldReceive(({message}) => | ||
expect(message.text).toBe('Hello, U14581577999389437648!') | ||
); | ||
``` | ||
|
||
As we finish the testing, we can let Jest know that we're done: | ||
|
||
```js | ||
user.then(done); | ||
``` | ||
|
||
## Usage | ||
|
||
### async/await | ||
|
||
You can use `await` with the mock user instance as it's a [thenable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise#thenables) class: | ||
|
||
```js | ||
await user.interactsWith(myBot); | ||
await user.sends({message: 'Hello!'}); | ||
``` | ||
|
||
### Mock Nodes | ||
|
||
A mock node is a fake ADAMANT Node that doesn't perform any calculations but returns mock data, which you are free to modify. | ||
|
||
When creating your first mock node, `botfactory-e2e` will try to find a free port starting from `36668`. Once it finds a free port, it will create a single server for all the features of the mock nodes: | ||
|
||
```js | ||
const node1 = createMockNode('first-node'); | ||
console.log(node1.url); // http://localhost:36668/first-node | ||
|
||
const node2 = createMockNode('second-node'); | ||
console.log(node2.url); // http://localhost:36668/second-node | ||
``` | ||
|
||
When creating a mock node, you must specify the fake node's ID, which you can use to clear the old node's data and reuse it: | ||
|
||
```js | ||
let node; | ||
|
||
beforeEach(() => { | ||
node = createMockNode('test-node'); | ||
}); | ||
``` | ||
|
||
Then, you can pass the created nodes into `createTestBot`: | ||
|
||
```js | ||
const testBot = createTestBot(bot, { | ||
nodes: [node1, node2], | ||
}); | ||
|
||
// Or for a single node, you can use | ||
|
||
const testBot = createTestBot(bot, { | ||
node: node1, | ||
}); | ||
``` | ||
|
||
### Test bot | ||
|
||
Test bot simply copies all the handlers from your bot and connects it with the fake nodes you provided, adding its keypair to the fake nodes data: | ||
|
||
```js | ||
const testBot = createTestBot(bot, { | ||
node, | ||
passphrase: | ||
'apple banana cherry date elderberry fig grape hazelnut iris juniper kiwi lemon', | ||
}); | ||
|
||
const {publicKey} = node.getAccount(testBot.address); | ||
|
||
// db299bb7fd288b387b0b94b539e2689c46f980ea7cfa0a53a26842f84f3c32bf | ||
console.log(publicKey); | ||
``` | ||
|
||
### Fake users | ||
|
||
To interact with your bot, you can use fake user. | ||
|
||
```js | ||
user | ||
.interactsWith(testBot) | ||
.sends({command: 'start'}) | ||
.shouldReceive(({message}) => | ||
expect(message.text).toBe('Hello, U14581577999389437648!') | ||
) | ||
.then(done); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import {globalNode} from 'adamant-botfactory-e2e'; | ||
|
||
globalNode.version('v0.6.0'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import {createFakeNode, createFakeUser} from 'adamant-botfactory-e2e'; | ||
import {bot} from '../bot.js'; | ||
|
||
let node: Node; | ||
|
||
beforeEach(() => { | ||
// Clear the node data before each test | ||
node = createMockNode('config-commands-test', { | ||
version: '0.6.0', | ||
}); | ||
}); | ||
|
||
it('should greet the users with their address', async () => { | ||
const testBot = createTestBot(bot, { | ||
nodes, | ||
}); | ||
|
||
const user = createFakeUser('my passphrase'); | ||
|
||
await user.interactsWith(testBot); | ||
await user.sends({command: 'start'}); | ||
|
||
const {message} = await user.shouldReceive(); | ||
|
||
await createFakeUser('my passphrase') | ||
.interactsWith(testBot) | ||
.sends({ | ||
command: 'start', | ||
}) | ||
.shouldReceive(({message}) => { | ||
expect(message).toBe('Welcome to test bot'); | ||
}) | ||
.transfers([0.5, 'BTC'], { | ||
withMessage: 'Take it', | ||
}) | ||
.shouldReceive(({message}) => { | ||
expect(message).toBe('Thanks for the donation!'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import {node, createFakeUser} from 'adamant-botfactory-e2e'; | ||
import {bot} from '../bot.js'; | ||
|
||
const nodeVersion = 'v0.6.0'; | ||
|
||
beforeAll(() => { | ||
node.version(nodeVersion); | ||
}); | ||
|
||
it('should greet the users with their address', done => { | ||
const user = createFakeUser('my passphrase', {node}); | ||
|
||
user | ||
.interactsWith(bot) | ||
.sends({command: 'start'}) | ||
.shouldReceive(({message}) => { | ||
expect(message).toBe( | ||
`Hello, ${user}. I am an example bot, I am connected to node ${nodeVersion}` | ||
); | ||
}) | ||
.then(done); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/** @type {import('ts-jest').JestConfigWithTsJest} */ | ||
module.exports = { | ||
preset: 'ts-jest/presets/js-with-ts', | ||
testEnvironment: 'node', | ||
transformIgnorePatterns: ['node_modules/.pnpm/(?!adamant-botfactory)'], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
{ | ||
"name": "botfactory-e2e", | ||
"version": "0.0.1", | ||
"description": "End-to-end testing framework for adamant-botfactory", | ||
"main": "dist/index.js", | ||
"type": "module", | ||
"scripts": { | ||
"lint": "gts lint", | ||
"test": "jest", | ||
"clean": "gts clean", | ||
"compile": "tsup-node src/index.ts", | ||
"fix": "gts fix", | ||
"prepare": "npm run compile", | ||
"preinstall": "npx only-allow pnpm", | ||
"format": "prettier --write ./src" | ||
}, | ||
"keywords": [ | ||
"ADAMANT" | ||
], | ||
"author": "", | ||
"license": "MIT", | ||
"files": [ | ||
"dist/" | ||
], | ||
"peerDependencies": { | ||
"adamant-botfactory": ">=0.2.1" | ||
}, | ||
"devDependencies": { | ||
"@types/express": "^4.17.21", | ||
"@types/jest": "^29.5.8", | ||
"@types/node": "20.8.2", | ||
"adamant-api": "^2.1.0", | ||
"gts": "^5.2.0", | ||
"jest": "^29.7.0", | ||
"ts-jest": "^29.1.1", | ||
"tsup": "^7.2.0", | ||
"typescript": "~5.2.0" | ||
}, | ||
"dependencies": { | ||
"axios": "^1.6.2", | ||
"express": "^4.18.2" | ||
} | ||
} |
Oops, something went wrong.