Skip to content

Commit b649796

Browse files
authored
fix: skip webhooks for flagged proposals (#147)
* fix: skip webhooks for flagged proposals * chore: setup tests * chore: add tests * chore: update CI to use node 18
1 parent 3db0115 commit b649796

File tree

7 files changed

+1881
-17
lines changed

7 files changed

+1881
-17
lines changed

.github/workflows/test.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: Test
2+
3+
on: [push]
4+
5+
jobs:
6+
test:
7+
strategy:
8+
matrix:
9+
target: ['18']
10+
uses: snapshot-labs/actions/.github/workflows/test.yml@main
11+
secrets: inherit
12+
with:
13+
target: ${{ matrix.target }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ node_modules
33
dist
44
build
55
.env
6+
coverage
67

78
# Remove some common IDE working directories
89
.idea

jest.config.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* For a detailed explanation regarding each configuration property and type check, visit:
3+
* https://jestjs.io/docs/configuration
4+
*/
5+
6+
export default {
7+
clearMocks: true,
8+
collectCoverage: true,
9+
collectCoverageFrom: ['./src/**'],
10+
coverageDirectory: 'coverage',
11+
coverageProvider: 'v8',
12+
coveragePathIgnorePatterns: ['/node_modules/', '<rootDir>/dist/', '<rootDir>/test/fixtures/'],
13+
preset: 'ts-jest',
14+
testEnvironment: 'jest-environment-node-single-context',
15+
setupFiles: ['dotenv/config'],
16+
moduleFileExtensions: ['js', 'ts'],
17+
verbose: true
18+
};

package.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"typecheck": "tsc --noEmit",
99
"build": "tsc",
1010
"dev": "nodemon src/index.ts",
11-
"start": "node dist/src/index.js"
11+
"start": "node dist/src/index.js",
12+
"test": "yarn jest"
1213
},
1314
"eslintConfig": {
1415
"extends": "@snapshot-labs"
@@ -43,9 +44,13 @@
4344
"@snapshot-labs/eslint-config": "^0.1.0-beta.15",
4445
"@snapshot-labs/prettier-config": "^0.1.0-beta.11",
4546
"@types/express": "^4.17.11",
47+
"@types/jest": "^29.5.10",
4648
"@types/node": "^18.0.0",
4749
"eslint": "^8.47.0",
48-
"prettier": "^3.0.3"
50+
"jest": "^29.7.0",
51+
"jest-environment-node-single-context": "^29.1.0",
52+
"prettier": "^3.0.3",
53+
"ts-jest": "^29.1.1"
4954
},
5055
"engines": {
5156
"node": "^18.0.0"

src/helpers/utils.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ export async function getSubscribers(space) {
3131
return subscriptions.map(subscription => subscription.address);
3232
}
3333

34-
export async function getProposal(id) {
35-
let proposal: { [key: string]: any } | null = null;
34+
export async function getProposal(id: string): Promise<Record<string, any> | null> {
3635
const query = {
3736
proposal: {
3837
__args: {
@@ -52,7 +51,8 @@ export async function getProposal(id) {
5251
start: true,
5352
end: true,
5453
link: true,
55-
snapshot: true
54+
snapshot: true,
55+
flagged: true
5656
}
5757
};
5858

@@ -61,8 +61,7 @@ export async function getProposal(id) {
6161
if (result.errors) {
6262
console.error(`[events] Errors in subgraph request for proposal id: ${id}`);
6363
}
64-
proposal = result.proposal || null;
65-
return proposal;
64+
return result.proposal?.flagged ? null : result.proposal || null;
6665
} catch (e: any) {
6766
capture(e, { contexts: { input: { query, id } } });
6867
return null;

test/unit/helpers/utils.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { getProposal } from '../../../src/helpers/utils';
2+
3+
const PROPOSAL = { id: '0x0', flagged: false };
4+
5+
const mockSnapshotUtilsSubgraphRequest = jest.fn((): any => {
6+
return {};
7+
});
8+
jest.mock('@snapshot-labs/snapshot.js', () => {
9+
const originalModule = jest.requireActual('@snapshot-labs/snapshot.js');
10+
11+
return {
12+
...originalModule,
13+
utils: {
14+
...originalModule.utils,
15+
subgraphRequest: () => mockSnapshotUtilsSubgraphRequest()
16+
}
17+
};
18+
});
19+
20+
describe('getProposal()', () => {
21+
it('returns null when the proposal is flagged', () => {
22+
mockSnapshotUtilsSubgraphRequest.mockResolvedValueOnce({
23+
proposal: { ...PROPOSAL, flagged: true }
24+
});
25+
expect(getProposal('')).resolves.toBeNull();
26+
});
27+
28+
it('returns null when the proposal does not exist', () => {
29+
mockSnapshotUtilsSubgraphRequest.mockResolvedValueOnce({ proposal: null });
30+
expect(getProposal('')).resolves.toBeNull();
31+
});
32+
33+
it('returns null on missing response', () => {
34+
mockSnapshotUtilsSubgraphRequest.mockResolvedValueOnce({});
35+
expect(getProposal('')).resolves.toBeNull();
36+
});
37+
38+
it('returns the proposal', () => {
39+
mockSnapshotUtilsSubgraphRequest.mockResolvedValueOnce({ proposal: PROPOSAL });
40+
expect(getProposal('')).resolves.toEqual(PROPOSAL);
41+
});
42+
});

0 commit comments

Comments
 (0)