Skip to content

Commit 261dcb1

Browse files
fix: prevent fetchUserContacts error when user has no contact (#64)
* fix: fix contact fetching error when user has no contacts * test: update and add tests
1 parent cae81f9 commit 261dcb1

File tree

2 files changed

+176
-109
lines changed

2 files changed

+176
-109
lines changed

src/utils/subgraphQuery.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ export const getValidContact = async (
2929
graphQLClient: GraphQLClient,
3030
contacts: Contact[]
3131
): Promise<Contact[]> => {
32+
if (contacts.length === 0) {
33+
return [];
34+
}
3235
try {
3336
// Contacts addresses
3437
const contactsAddresses = contacts.map((contact) => contact.address);

tests/e2e/fetchUserContacts.test.ts

Lines changed: 173 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -42,115 +42,179 @@ describe('web3telegram.fetchMyContacts()', () => {
4242
await waitSubgraphIndexing();
4343
}, 4 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME);
4444

45-
it(
46-
'Tow different user should have different contacts',
47-
async () => {
48-
const user1 = Wallet.createRandom().address;
49-
const user2 = Wallet.createRandom().address;
50-
const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID);
51-
await dataProtector.grantAccess({
52-
authorizedApp: defaultConfig.dappAddress,
53-
protectedData: protectedData1.address,
54-
authorizedUser: user1,
55-
});
56-
57-
await dataProtector.grantAccess({
58-
authorizedApp: defaultConfig.dappAddress,
59-
protectedData: protectedData2.address,
60-
authorizedUser: user2,
61-
});
62-
63-
const contactUser1 = await web3telegram.fetchUserContacts({
64-
userAddress: user1,
65-
});
66-
const contactUser2 = await web3telegram.fetchUserContacts({
67-
userAddress: user2,
68-
});
69-
expect(contactUser1).not.toEqual(contactUser2);
70-
},
71-
MAX_EXPECTED_WEB2_SERVICES_TIME
72-
);
73-
74-
it(
75-
'Test that the protected data can be accessed by authorized user',
76-
async () => {
77-
const userWithAccess = Wallet.createRandom().address;
78-
const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID);
79-
await dataProtector.grantAccess({
80-
authorizedApp: defaultConfig.dappAddress,
81-
protectedData: protectedData1.address,
82-
authorizedUser: userWithAccess,
83-
});
84-
85-
const contacts = await web3telegram.fetchUserContacts({
86-
userAddress: userWithAccess,
87-
});
88-
expect(contacts.length).toBeGreaterThan(0);
89-
},
90-
MAX_EXPECTED_WEB2_SERVICES_TIME
91-
);
92-
93-
it(
94-
'should throw a protocol error',
95-
async () => {
96-
// Call getTestConfig to get the default configuration
97-
const [ethProvider, defaultOptions] = getTestConfig(wallet.privateKey);
98-
const user1 = Wallet.createRandom().address;
99-
100-
const options = {
101-
...defaultOptions,
102-
iexecOptions: {
103-
...defaultOptions.iexecOptions,
104-
iexecGatewayURL: 'https://test',
105-
},
106-
};
107-
108-
// Pass the modified options to IExecWeb3telegram
109-
const invalidWeb3telegram = new IExecWeb3telegram(ethProvider, options);
110-
let error: WorkflowError | undefined;
111-
112-
try {
113-
await invalidWeb3telegram.fetchUserContacts({
45+
describe('when no access is granted', () => {
46+
it(
47+
'should return an empty contact array',
48+
async () => {
49+
const noAccessUser = Wallet.createRandom().address;
50+
51+
const contacts = await web3telegram.fetchUserContacts({
52+
userAddress: noAccessUser,
53+
isUserStrict: true,
54+
});
55+
console.log('🚀 ~ contacts:', contacts);
56+
57+
expect(contacts.length).toBe(0);
58+
},
59+
2 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME
60+
);
61+
});
62+
63+
describe('when access is granted', () => {
64+
it(
65+
'should return the user contacts for both app and whitelist',
66+
async () => {
67+
const userWithAccess = Wallet.createRandom().address;
68+
const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID);
69+
expect(defaultConfig).not.toBeNull();
70+
const authorizedApp = defaultConfig!.dappAddress;
71+
const authorizedWhitelist = defaultConfig!.whitelistSmartContract;
72+
73+
await dataProtector.grantAccess({
74+
authorizedApp: authorizedApp,
75+
protectedData: protectedData1.address,
76+
authorizedUser: userWithAccess,
77+
});
78+
79+
await dataProtector.grantAccess({
80+
authorizedApp: authorizedWhitelist,
81+
protectedData: protectedData2.address,
82+
authorizedUser: userWithAccess,
83+
});
84+
85+
const contacts = await web3telegram.fetchUserContacts({
86+
userAddress: userWithAccess,
87+
isUserStrict: true,
88+
});
89+
expect(contacts.length).toBe(2);
90+
},
91+
MAX_EXPECTED_WEB2_SERVICES_TIME
92+
);
93+
94+
it(
95+
'Two different user should have different contacts',
96+
async () => {
97+
const user1 = Wallet.createRandom().address;
98+
const user2 = Wallet.createRandom().address;
99+
const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID);
100+
await dataProtector.grantAccess({
101+
authorizedApp: defaultConfig.dappAddress,
102+
protectedData: protectedData1.address,
103+
authorizedUser: user1,
104+
});
105+
106+
await dataProtector.grantAccess({
107+
authorizedApp: defaultConfig.dappAddress,
108+
protectedData: protectedData2.address,
109+
authorizedUser: user2,
110+
});
111+
112+
const contactUser1 = await web3telegram.fetchUserContacts({
114113
userAddress: user1,
115114
});
116-
} catch (err) {
117-
error = err as WorkflowError;
118-
}
119-
120-
expect(error).toBeInstanceOf(WorkflowError);
121-
expect(error?.message).toBe(
122-
"A service in the iExec protocol appears to be unavailable. You can retry later or contact iExec's technical support for help."
123-
);
124-
expect(error?.isProtocolError).toBe(true);
125-
},
126-
2 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME
127-
);
128-
129-
it(
130-
'should throw a fetchUserContacts error',
131-
async () => {
132-
// Call getTestConfig to get the default configuration
133-
const [ethProvider, defaultOptions] = getTestConfig(wallet.privateKey);
134-
135-
const options = {
136-
...defaultOptions,
137-
dataProtectorSubgraph: 'https://test',
138-
};
139-
140-
// Pass the modified options to IExecWeb3telegram
141-
const invalidWeb3telegram = new IExecWeb3telegram(ethProvider, options);
142-
let error: WorkflowError | undefined;
143-
144-
try {
145-
await invalidWeb3telegram.fetchMyContacts();
146-
} catch (err) {
147-
error = err as WorkflowError;
148-
}
149-
150-
expect(error).toBeInstanceOf(WorkflowError);
151-
expect(error?.message).toBe('Failed to fetch user contacts');
152-
expect(error?.isProtocolError).toBe(false);
153-
},
154-
2 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME
155-
);
115+
const contactUser2 = await web3telegram.fetchUserContacts({
116+
userAddress: user2,
117+
});
118+
expect(contactUser1).not.toEqual(contactUser2);
119+
},
120+
MAX_EXPECTED_WEB2_SERVICES_TIME
121+
);
122+
123+
it(
124+
'Test that the protected data can be accessed by authorized user',
125+
async () => {
126+
const userWithAccess = Wallet.createRandom().address;
127+
const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID);
128+
await dataProtector.grantAccess({
129+
authorizedApp: defaultConfig.dappAddress,
130+
protectedData: protectedData1.address,
131+
authorizedUser: userWithAccess,
132+
});
133+
134+
const contacts = await web3telegram.fetchUserContacts({
135+
userAddress: userWithAccess,
136+
});
137+
expect(contacts.length).toBeGreaterThan(0);
138+
},
139+
MAX_EXPECTED_WEB2_SERVICES_TIME
140+
);
141+
});
142+
143+
describe('when iexec market API is not reachable', () => {
144+
it(
145+
'should throw a protocol error',
146+
async () => {
147+
// Call getTestConfig to get the default configuration
148+
const [ethProvider, defaultOptions] = getTestConfig(wallet.privateKey);
149+
const user1 = Wallet.createRandom().address;
150+
151+
const options = {
152+
...defaultOptions,
153+
iexecOptions: {
154+
...defaultOptions.iexecOptions,
155+
iexecGatewayURL: 'https://test',
156+
},
157+
};
158+
159+
// Pass the modified options to IExecWeb3telegram
160+
const invalidWeb3telegram = new IExecWeb3telegram(ethProvider, options);
161+
let error: WorkflowError | undefined;
162+
163+
try {
164+
await invalidWeb3telegram.fetchUserContacts({
165+
userAddress: user1,
166+
});
167+
} catch (err) {
168+
error = err as WorkflowError;
169+
}
170+
171+
expect(error).toBeInstanceOf(WorkflowError);
172+
expect(error?.message).toBe(
173+
"A service in the iExec protocol appears to be unavailable. You can retry later or contact iExec's technical support for help."
174+
);
175+
expect(error?.isProtocolError).toBe(true);
176+
},
177+
2 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME
178+
);
179+
});
180+
181+
describe('when subgraph is not reachable', () => {
182+
it(
183+
'should throw a fetchUserContacts error',
184+
async () => {
185+
// Call getTestConfig to get the default configuration
186+
const [ethProvider, defaultOptions] = getTestConfig(wallet.privateKey);
187+
188+
const defaultConfig = getChainDefaultConfig(DEFAULT_CHAIN_ID);
189+
expect(defaultConfig).not.toBeNull();
190+
const authorizedApp = defaultConfig!.dappAddress;
191+
192+
await dataProtector.grantAccess({
193+
authorizedApp: authorizedApp,
194+
protectedData: protectedData1.address,
195+
authorizedUser: ethProvider.address,
196+
});
197+
198+
const options = {
199+
...defaultOptions,
200+
dataProtectorSubgraph: 'https://test',
201+
};
202+
203+
// Pass the modified options to IExecWeb3telegram
204+
const invalidWeb3telegram = new IExecWeb3telegram(ethProvider, options);
205+
let error: WorkflowError | undefined;
206+
207+
try {
208+
await invalidWeb3telegram.fetchMyContacts();
209+
} catch (err) {
210+
error = err as WorkflowError;
211+
}
212+
213+
expect(error).toBeInstanceOf(WorkflowError);
214+
expect(error?.message).toBe('Failed to fetch user contacts');
215+
expect(error?.isProtocolError).toBe(false);
216+
},
217+
2 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME
218+
);
219+
});
156220
});

0 commit comments

Comments
 (0)