-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement e2e test flow, fix small bugs #65
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
# common | ||
|
||
Utilities commonly used by other packages. Each common utility lives in its own folder together with its documentation. | ||
The implementation is re-exported by main entry of this package. The package consists of: | ||
> Utilities commonly used by other packages. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To make it consistent with other packages. |
||
|
||
Each common utility lives in its own folder together with its documentation. The implementation is re-exported by main | ||
entry of this package. The package consists of: | ||
|
||
- [logger](./src/logger) - Backend-only logger for Node.js packages based on Winston logger. | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,15 +87,15 @@ export interface Logger { | |
// That's causing an override of fields `name` and `message` if they are present. | ||
const wrapper = (logger: Logger): Logger => { | ||
return { | ||
debug: (message, context) => logger.debug(message, { context }), | ||
info: (message, context) => logger.info(message, { context }), | ||
warn: (message, context) => logger.warn(message, { context }), | ||
debug: (message, context) => logger.debug(message, context ? { context } : undefined), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you do not pass |
||
info: (message, context) => logger.info(message, context ? { context } : undefined), | ||
warn: (message, context) => logger.warn(message, context ? { context } : undefined), | ||
// We need to handle both overloads of the `error` function | ||
error: (message, errorOrContext, context) => { | ||
if (errorOrContext instanceof Error) { | ||
logger.error(message, errorOrContext, { context }); | ||
logger.error(message, errorOrContext, context ? { context } : undefined); | ||
} else { | ||
logger.error(message, { context: errorOrContext }); | ||
logger.error(message, errorOrContext ? { context: errorOrContext } : undefined); | ||
} | ||
}, | ||
child: (options) => wrapper(logger.child(options)), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# NOTE: Keep in sync with .dockerignore | ||
.build | ||
.env | ||
.idea | ||
.log | ||
.tsbuildinfo | ||
.vscode | ||
build | ||
dist | ||
node_modules | ||
coverage | ||
pusher.json | ||
secrets.env | ||
signed-api.json | ||
.DS_Store |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# NOTE: Keep in sync with .dockerignore | ||
.build | ||
.env | ||
.idea | ||
.log | ||
.tsbuildinfo | ||
.vscode | ||
build | ||
dist | ||
node_modules | ||
coverage | ||
pusher.json | ||
secrets.env | ||
signed-api.json | ||
.DS_Store |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# e2e | ||
|
||
> End to end test utilizing Mock API, pusher and signed API. | ||
|
||
## Getting started | ||
|
||
1. If you are using Docker Desktop, you need to change the URL in `pusher/secrets.env` from `localhost` to | ||
`host.docker.internal`, because pusher is running inside a Docker container. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the configurations are not gitignored it will modify source tree, but I don't think we need to care much. |
||
2. Build the latest Docker images. Run `pnpm run docker:build` from the monorepo root. The e2e flow uses the docker | ||
images. | ||
3. This module contains services (or configurations) that are integrated together. Specifically: | ||
|
||
- `pusher` - Contains the configuration for the pusher service. | ||
- `signed-api` - Contains the configuration for the signed API service. | ||
- `data-provider-api.ts` - Contains the configuration for the data provider API service (mocked express server). | ||
- `user.ts` - Contains the configuration for the user service (infinite fetch from signed API). | ||
|
||
You are free to modify the configurations to test different scenarios. | ||
|
||
4. There are `start:<some-service>` scripts to start the services. It is recommended to start each service in a separate | ||
terminal and in this order: | ||
|
||
1. `pnpm run start:data-provider-api` | ||
2. `pnpm run start:signed-api` | ||
3. `pnpm run start:pusher` | ||
4. `pnpm run start:user` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
const config = require('../../jest.config'); | ||
|
||
module.exports = { | ||
...config, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"name": "e2e", | ||
"version": "1.0.0", | ||
"engines": { | ||
"node": "^18.14.0", | ||
"pnpm": "^8.8.0" | ||
}, | ||
"scripts": { | ||
"build": "tsc --project tsconfig.build.json", | ||
"clean": "rm -rf coverage dist", | ||
"eslint:check": "eslint . --ext .js,.ts --max-warnings 0", | ||
"eslint:fix": "eslint . --ext .js,.ts --fix", | ||
"prettier:check": "prettier --check \"./**/*.{js,ts,md,yml,json}\"", | ||
"prettier:fix": "prettier --write \"./**/*.{js,ts,md,yml,json}\"", | ||
"start:data-provider-api": "ts-node src/data-provider-api.ts", | ||
"start:pusher": "docker run -it --init --volume $(pwd)/src/pusher:/app/config --env-file ./src/pusher/.env --rm --memory=256m pusher:latest", | ||
"start:signed-api": "docker run --publish 8090:8090 -it --init --volume $(pwd)/src/signed-api:/app/config --env-file ./src/signed-api/.env --rm --memory=256m api:latest", | ||
"start:user": "ts-node src/user.ts", | ||
"test": "jest --passWithNoTests", | ||
"test:e2e": "jest", | ||
"tsc": "tsc --project ." | ||
}, | ||
"license": "MIT", | ||
"dependencies": { | ||
"@api3/promise-utils": "^0.4.0", | ||
"axios": "^1.5.1", | ||
"ethers": "^5.7.2", | ||
"express": "^4.18.2", | ||
"lodash": "^4.17.21", | ||
"signed-api/common": "workspace:common@*", | ||
"zod": "^3.22.2" | ||
}, | ||
"devDependencies": { | ||
"@types/express": "^4.17.18", | ||
"@types/lodash": "^4.14.199" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import express from 'express'; | ||
import { logger } from './logger'; | ||
|
||
const app = express(); | ||
const PORT = 9876 || process.env.PORT; | ||
|
||
interface Asset { | ||
value: number; | ||
// Everytime the API is queried, the value will be updated by a random percentage. | ||
deltaPercent: number; | ||
name: string; | ||
} | ||
|
||
const assets: Asset[] = [ | ||
{ | ||
value: 1000, | ||
deltaPercent: 10, | ||
name: 'MOCK-ETH/USD', | ||
}, | ||
{ | ||
value: 5000, | ||
deltaPercent: 2, | ||
name: 'MOCK-BTC/USD', | ||
}, | ||
{ | ||
value: 750, | ||
deltaPercent: 80, | ||
name: 'MOCK-ABC/DEF', | ||
}, | ||
{ | ||
value: 50000, | ||
deltaPercent: 20, | ||
name: 'MOCK-HJK/KOP', | ||
}, | ||
]; | ||
|
||
app.get('/', (_req, res) => { | ||
logger.debug('Request GET /'); | ||
|
||
for (const asset of assets) { | ||
asset.value = parseFloat((asset.value * (1 + ((Math.random() - 0.5) * asset.deltaPercent) / 100)).toFixed(5)); | ||
} | ||
|
||
const response = Object.fromEntries(assets.map((asset) => [asset.name, asset.value])); | ||
logger.debug('Response GET /', response); | ||
|
||
res.json(response); | ||
}); | ||
|
||
app.listen(PORT, () => { | ||
logger.info(`Server is running on http://localhost:${PORT}`); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { createLogger } from 'signed-api/common'; | ||
|
||
export const logger = createLogger({ | ||
colorize: true, | ||
enabled: true, | ||
minLevel: 'debug', | ||
format: 'pretty', | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
LOGGER_ENABLED=true | ||
LOG_COLORIZE=true | ||
LOG_FORMAT=pretty | ||
LOG_LEVEL=debug |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was too spammy. Note, that I still left the receive log as INFO level.