diff --git a/e2e/specs/stateless/extendNames.spec.ts b/e2e/specs/stateless/extendNames.spec.ts
index e0dbea69b..b13b390ee 100644
--- a/e2e/specs/stateless/extendNames.spec.ts
+++ b/e2e/specs/stateless/extendNames.spec.ts
@@ -11,7 +11,7 @@ import { daysToSeconds } from '@app/utils/time'
import { test } from '../../../playwright'
-test('should be able to register multiple names on the address page', async ({
+test('should be able to extend multiple names (including names in grace preiod) on the address page', async ({
page,
accounts,
login,
@@ -26,11 +26,13 @@ test('should be able to register multiple names on the address page', async ({
label: 'extend-legacy',
type: 'legacy',
owner: 'user2',
+ duration: -24 * 60 * 60,
},
{
label: 'wrapped',
type: 'wrapped',
owner: 'user2',
+ duration: -24 * 60 * 60,
},
])
@@ -65,29 +67,27 @@ test('should be able to register multiple names on the address page', async ({
// warning message
await expect(page.getByText('You do not own all these names')).toBeVisible()
- await page.locator('button:has-text("I understand")').click()
+ await page.getByTestId('extend-names-confirm').click()
// name list
- await page.waitForLoadState('networkidle')
await expect(page.getByText(`Extend ${extendableNameItems.length} Names`)).toBeVisible()
- page.locator('button:has-text("Next")').waitFor({ state: 'visible' })
+ await page.locator('button:has-text("Next")').waitFor({ state: 'visible' })
await page.locator('button:has-text("Next")').click()
// check the invoice details
- await page.waitForLoadState('networkidle')
- await expect(page.getByText('1 year extension', { exact: true })).toBeVisible()
- // increment and save
+ // TODO: Reimplement when date duration bug is fixed
+ // await expect(page.getByText('1 year extension', { exact: true })).toBeVisible()
+ await expect(page.getByTestId('plus-minus-control-label')).toHaveText('1 year')
await page.getByTestId('plus-minus-control-plus').click()
+ await expect(page.getByTestId('plus-minus-control-label')).toHaveText('2 years')
await page.getByTestId('plus-minus-control-plus').click()
- await page.waitForLoadState('networkidle')
- await expect(page.getByTestId('invoice-item-0-amount')).not.toBeEmpty()
- await expect(page.getByTestId('invoice-item-1-amount')).not.toBeEmpty()
- await expect(page.getByTestId('invoice-total')).not.toBeEmpty()
-
- page.locator('button:has-text("Next")').waitFor({ state: 'visible' })
- await page.locator('button:has-text("Next")').click()
- await page.waitForLoadState('networkidle')
+ await expect(page.getByTestId('plus-minus-control-label')).toHaveText('3 years')
+ await expect(page.getByTestId('invoice-item-0-amount')).not.toHaveText('0.0000 ETH')
+ await expect(page.getByTestId('invoice-item-1-amount')).not.toHaveText('0.0000 ETH')
+ await expect(page.getByTestId('invoice-total')).not.toHaveText('0.0000 ETH')
+ await page.getByTestId('extend-names-confirm').click()
+ await expect(transactionModal.transactionModal).toBeVisible({ timeout: 10000 })
await transactionModal.autoComplete()
await expect(page.getByText('Your "Extend names" transaction was successful')).toBeVisible({
@@ -373,7 +373,7 @@ test('should be able to extend a name by a month', async ({
await test.step('should show the correct price data', async () => {
await expect(extendNamesModal.getInvoiceExtensionFee).toContainText('0.0003')
await expect(extendNamesModal.getInvoiceTransactionFee).toContainText('0.0001')
- await expect(extendNamesModal.getInvoiceTotal).toContainText('0.0004')
+ await expect(extendNamesModal.getInvoiceTotal).toContainText(/0\.000[3|4]/)
await expect(page.getByText(/1 month .* extension/)).toBeVisible()
})
diff --git a/e2e/specs/stateless/verifications.spec.ts b/e2e/specs/stateless/verifications.spec.ts
index 3f23e22e4..f96b06b33 100644
--- a/e2e/specs/stateless/verifications.spec.ts
+++ b/e2e/specs/stateless/verifications.spec.ts
@@ -16,12 +16,19 @@ import {
import { createAccounts } from '../../../playwright/fixtures/accounts'
import { testClient } from '../../../playwright/fixtures/contracts/utils/addTestContracts'
+type MakeMockVPTokenRecordKey =
+ | 'com.twitter'
+ | 'com.github'
+ | 'com.discord'
+ | 'org.telegram'
+ | 'personhood'
+ | 'email'
+ | 'ens'
+
const makeMockVPToken = (
- records: Array<
- 'com.twitter' | 'com.github' | 'com.discord' | 'org.telegram' | 'personhood' | 'email'
- >,
+ records: Array<{ key: MakeMockVPTokenRecordKey; value?: string; name?: string }>,
) => {
- return records.map((record) => ({
+ return records.map(({ key, value, name }) => ({
type: [
'VerifiableCredential',
{
@@ -31,15 +38,22 @@ const makeMockVPToken = (
'org.telegram': 'VerifiedTelegramAccount',
personhood: 'VerifiedPersonhood',
email: 'VerifiedEmail',
- }[record],
+ ens: 'VerifiedENS',
+ }[key],
],
credentialSubject: {
credentialIssuer: 'Dentity',
- ...(record === 'com.twitter' ? { username: '@name' } : {}),
- ...(['com.twitter', 'com.github', 'com.discord', 'org.telegram'].includes(record)
- ? { name: 'name' }
+ ...(key === 'com.twitter' ? { username: value ?? '@name' } : {}),
+ ...(['com.twitter', 'com.github', 'com.discord', 'org.telegram'].includes(key)
+ ? { name: value ?? 'name' }
+ : {}),
+ ...(key === 'email' ? { verifiedEmail: value ?? 'name@email.com' } : {}),
+ ...(key === 'ens'
+ ? {
+ ensName: name ?? 'name.eth',
+ ethAddress: value ?? (createAccounts().getAddress('user') as Hash),
+ }
: {}),
- ...(record === 'email' ? { verifiedEmail: 'name@email.com' } : {}),
},
}))
}
@@ -94,12 +108,13 @@ test.describe('Verified records', () => {
contentType: 'application/json',
body: JSON.stringify({
vp_token: makeMockVPToken([
- 'com.twitter',
- 'com.github',
- 'com.discord',
- 'org.telegram',
- 'personhood',
- 'email',
+ { key: 'com.twitter' },
+ { key: 'com.github' },
+ { key: 'com.discord' },
+ { key: 'org.telegram' },
+ { key: 'personhood' },
+ { key: 'email' },
+ { key: 'ens', name },
]),
}),
})
@@ -108,8 +123,6 @@ test.describe('Verified records', () => {
await page.goto(`/${name}`)
// await login.connect()
- await page.pause()
-
await expect(page.getByTestId('profile-section-verifications')).toBeVisible()
await profilePage.isRecordVerified('text', 'com.twitter')
@@ -173,7 +186,161 @@ test.describe('Verified records', () => {
body: JSON.stringify({
ens_name: name,
eth_address: accounts.getAddress('user2'),
- vp_token: makeMockVPToken(['com.twitter', 'com.github', 'com.discord', 'org.telegram']),
+ vp_token: makeMockVPToken([
+ { key: 'com.twitter' },
+ { key: 'com.github' },
+ { key: 'com.discord' },
+ { key: 'org.telegram' },
+ { key: 'ens', name },
+ ]),
+ }),
+ })
+ })
+
+ await page.goto(`/${name}`)
+
+ await expect(page.getByTestId('profile-section-verifications')).toBeVisible()
+
+ await profilePage.isRecordVerified('text', 'com.twitter', false)
+ await profilePage.isRecordVerified('text', 'org.telegram', false)
+ await profilePage.isRecordVerified('text', 'com.github', false)
+ await profilePage.isRecordVerified('text', 'com.discord', false)
+ await profilePage.isRecordVerified('verification', 'dentity', false)
+ await profilePage.isPersonhoodVerified(false)
+
+ await expect(profilePage.record('verification', 'dentity')).toBeVisible()
+ await expect(profilePage.record('verification', 'dentity')).toBeVisible()
+ })
+
+ test('Should not show badges if records match but ens credential address does not match', async ({
+ page,
+ accounts,
+ makePageObject,
+ makeName,
+ }) => {
+ const name = await makeName({
+ label: 'dentity',
+ type: 'wrapped',
+ owner: 'user',
+ records: {
+ texts: [
+ {
+ key: 'com.twitter',
+ value: '@name',
+ },
+ {
+ key: 'org.telegram',
+ value: 'name',
+ },
+ {
+ key: 'com.discord',
+ value: 'name',
+ },
+ {
+ key: 'com.github',
+ value: 'name',
+ },
+ {
+ key: VERIFICATION_RECORD_KEY,
+ value: JSON.stringify([
+ `${DENTITY_VPTOKEN_ENDPOINT}?name=name.eth&federated_token=federated_token`,
+ ]),
+ },
+ ],
+ },
+ })
+
+ const profilePage = makePageObject('ProfilePage')
+
+ await page.route(`${DENTITY_VPTOKEN_ENDPOINT}*`, async (route) => {
+ await route.fulfill({
+ status: 200,
+ contentType: 'application/json',
+ body: JSON.stringify({
+ ens_name: name,
+ eth_address: accounts.getAddress('user2'),
+ vp_token: makeMockVPToken([
+ { key: 'com.twitter' },
+ { key: 'com.github' },
+ { key: 'com.discord' },
+ { key: 'org.telegram' },
+ { key: 'ens', name, value: accounts.getAddress('user2') },
+ ]),
+ }),
+ })
+ })
+
+ await page.goto(`/${name}`)
+
+ await page.pause()
+
+ await expect(page.getByTestId('profile-section-verifications')).toBeVisible()
+
+ await profilePage.isRecordVerified('text', 'com.twitter', false)
+ await profilePage.isRecordVerified('text', 'org.telegram', false)
+ await profilePage.isRecordVerified('text', 'com.github', false)
+ await profilePage.isRecordVerified('text', 'com.discord', false)
+ await profilePage.isRecordVerified('verification', 'dentity', false)
+ await profilePage.isPersonhoodVerified(false)
+
+ await expect(profilePage.record('verification', 'dentity')).toBeVisible()
+ await expect(profilePage.record('verification', 'dentity')).toBeVisible()
+ })
+
+ test('Should not show badges if records match but ens credential name does not match', async ({
+ page,
+ accounts,
+ makePageObject,
+ makeName,
+ }) => {
+ const name = await makeName({
+ label: 'dentity',
+ type: 'wrapped',
+ owner: 'user',
+ records: {
+ texts: [
+ {
+ key: 'com.twitter',
+ value: '@name',
+ },
+ {
+ key: 'org.telegram',
+ value: 'name',
+ },
+ {
+ key: 'com.discord',
+ value: 'name',
+ },
+ {
+ key: 'com.github',
+ value: 'name',
+ },
+ {
+ key: VERIFICATION_RECORD_KEY,
+ value: JSON.stringify([
+ `${DENTITY_VPTOKEN_ENDPOINT}?name=name.eth&federated_token=federated_token`,
+ ]),
+ },
+ ],
+ },
+ })
+
+ const profilePage = makePageObject('ProfilePage')
+
+ await page.route(`${DENTITY_VPTOKEN_ENDPOINT}*`, async (route) => {
+ await route.fulfill({
+ status: 200,
+ contentType: 'application/json',
+ body: JSON.stringify({
+ ens_name: name,
+ eth_address: accounts.getAddress('user2'),
+ vp_token: makeMockVPToken([
+ { key: 'com.twitter' },
+ { key: 'com.github' },
+ { key: 'com.discord' },
+ { key: 'org.telegram' },
+ { key: 'ens', name: 'differentName.eth' },
+ ]),
}),
})
})
@@ -194,6 +361,89 @@ test.describe('Verified records', () => {
await expect(profilePage.record('verification', 'dentity')).toBeVisible()
await expect(profilePage.record('verification', 'dentity')).toBeVisible()
})
+
+ test('Should show error icon on verication button if VerifiedENS credential is not validated', async ({
+ page,
+ login,
+ makePageObject,
+ makeName,
+ }) => {
+ const name = await makeName({
+ label: 'dentity',
+ type: 'wrapped',
+ owner: 'user',
+ records: {
+ texts: [
+ {
+ key: 'com.twitter',
+ value: '@name',
+ },
+ {
+ key: 'org.telegram',
+ value: 'name',
+ },
+ {
+ key: 'com.discord',
+ value: 'name',
+ },
+ {
+ key: 'com.github',
+ value: 'name',
+ },
+ {
+ key: 'email',
+ value: 'name@email.com',
+ },
+ {
+ key: VERIFICATION_RECORD_KEY,
+ value: JSON.stringify([
+ `${DENTITY_VPTOKEN_ENDPOINT}?name=name.eth&federated_token=federated_token`,
+ ]),
+ },
+ {
+ key: 'com.twitter',
+ value: '@name',
+ },
+ ],
+ },
+ })
+
+ const profilePage = makePageObject('ProfilePage')
+
+ await page.route(`${DENTITY_VPTOKEN_ENDPOINT}*`, async (route) => {
+ await route.fulfill({
+ status: 200,
+ contentType: 'application/json',
+ body: JSON.stringify({
+ vp_token: makeMockVPToken([
+ { key: 'com.twitter' },
+ { key: 'com.github' },
+ { key: 'com.discord' },
+ { key: 'org.telegram' },
+ { key: 'personhood' },
+ { key: 'email' },
+ { key: 'ens', name: 'othername.eth' },
+ ]),
+ }),
+ })
+ })
+
+ await page.goto(`/${name}`)
+ await login.connect()
+
+ await page.pause()
+
+ await expect(page.getByTestId('profile-section-verifications')).toBeVisible()
+
+ await profilePage.isRecordVerified('text', 'com.twitter', false)
+ await profilePage.isRecordVerified('text', 'org.telegram', false)
+ await profilePage.isRecordVerified('text', 'com.github', false)
+ await profilePage.isRecordVerified('text', 'com.discord', false)
+ await profilePage.isRecordVerified('verification', 'dentity', false)
+ await profilePage.isPersonhoodErrored()
+
+ await expect(profilePage.record('verification', 'dentity')).toBeVisible()
+ })
})
test.describe('Verify profile', () => {
@@ -219,11 +469,11 @@ test.describe('Verify profile', () => {
contentType: 'application/json',
body: JSON.stringify({
vp_token: makeMockVPToken([
- 'personhood',
- 'com.twitter',
- 'com.github',
- 'com.discord',
- 'org.telegram',
+ { key: 'personhood' },
+ { key: 'com.twitter' },
+ { key: 'com.github' },
+ { key: 'com.discord' },
+ { key: 'org.telegram' },
]),
}),
})
@@ -263,11 +513,11 @@ test.describe('Verify profile', () => {
contentType: 'application/json',
body: JSON.stringify({
vp_token: makeMockVPToken([
- 'personhood',
- 'com.twitter',
- 'com.github',
- 'com.discord',
- 'org.telegram',
+ { key: 'personhood' },
+ { key: 'com.twitter' },
+ { key: 'com.github' },
+ { key: 'com.discord' },
+ { key: 'org.telegram' },
]),
}),
})
@@ -332,11 +582,12 @@ test.describe('Verify profile', () => {
contentType: 'application/json',
body: JSON.stringify({
vp_token: makeMockVPToken([
- 'personhood',
- 'com.twitter',
- 'com.github',
- 'com.discord',
- 'org.telegram',
+ { key: 'personhood' },
+ { key: 'com.twitter' },
+ { key: 'com.github' },
+ { key: 'com.discord' },
+ { key: 'org.telegram' },
+ { key: 'ens', name, value: createAccounts().getAddress('user2') },
]),
}),
})
@@ -345,8 +596,6 @@ test.describe('Verify profile', () => {
await profilePage.goto(name)
await login.connect()
- await page.pause()
-
await expect(page.getByTestId('profile-section-verifications')).toBeVisible()
await profilePage.isRecordVerified('text', 'com.twitter')
@@ -374,7 +623,6 @@ test.describe('Verify profile', () => {
await profilePage.isRecordVerified('text', 'com.discord', false)
await profilePage.isRecordVerified('verification', 'dentity', false)
await profilePage.isPersonhoodVerified(false)
- await page.pause()
})
})
@@ -432,11 +680,12 @@ test.describe('OAuth flow', () => {
contentType: 'application/json',
body: JSON.stringify({
vp_token: makeMockVPToken([
- 'personhood',
- 'com.twitter',
- 'com.github',
- 'com.discord',
- 'org.telegram',
+ { key: 'personhood' },
+ { key: 'com.twitter' },
+ { key: 'com.github' },
+ { key: 'com.discord' },
+ { key: 'org.telegram' },
+ { key: 'ens', name, value: createAccounts().getAddress('user2') },
]),
}),
})
@@ -488,8 +737,6 @@ test.describe('OAuth flow', () => {
await page.goto(`/?iss=${DENTITY_ISS}&code=dummyCode`)
await login.connect()
- await page.pause()
-
await expect(page.getByText('Verification failed')).toBeVisible()
await expect(
page.getByText(
@@ -497,13 +744,10 @@ test.describe('OAuth flow', () => {
),
).toBeVisible()
- await page.pause()
await login.switchTo('user2')
// Page should redirect to the profile page
await expect(page).toHaveURL(`/${name}`)
-
- await page.pause()
})
test('Should show an error message if user is not logged in', async ({
@@ -531,8 +775,6 @@ test.describe('OAuth flow', () => {
await page.goto(`/?iss=${DENTITY_ISS}&code=dummyCode`)
- await page.pause()
-
await expect(page.getByText('Verification failed')).toBeVisible()
await expect(
page.getByText('You must be connected as 0x709...c79C8 to set the verification record.'),
@@ -540,13 +782,21 @@ test.describe('OAuth flow', () => {
await page.locator('.modal').getByRole('button', { name: 'Done' }).click()
- await page.pause()
+ await page.route(`${VERIFICATION_OAUTH_BASE_URL}/dentity/token`, async (route) => {
+ await route.fulfill({
+ status: 401,
+ contentType: 'application/json',
+ body: JSON.stringify({
+ error_msg: 'Unauthorized',
+ }),
+ })
+ })
+
await login.connect('user2')
+ await page.reload()
// Page should redirect to the profile page
await expect(page).toHaveURL(`/${name}`)
-
- await page.pause()
})
test('Should redirect to profile page without showing set verification record if it already set', async ({
@@ -594,15 +844,9 @@ test.describe('OAuth flow', () => {
await expect(page).toHaveURL(`/${name}`)
await expect(transactionModal.transactionModal).not.toBeVisible()
-
- await page.pause()
})
- test('Should show general error message if other problems occur', async ({
- page,
- login,
- makeName,
- }) => {
+ test('Should show general error message if other problems occur', async ({ page, makeName }) => {
const name = await makeName({
label: 'dentity',
type: 'legacy',
@@ -622,9 +866,6 @@ test.describe('OAuth flow', () => {
})
await page.goto(`/?iss=${DENTITY_ISS}&code=dummyCode`)
- await login.connect('user')
-
- await page.pause()
await expect(page.getByText('Verification failed')).toBeVisible()
await expect(
diff --git a/package.json b/package.json
index 1e3666f84..4558ec1e7 100644
--- a/package.json
+++ b/package.json
@@ -65,6 +65,7 @@
"@tanstack/query-persist-client-core": "5.22.2",
"@tanstack/query-sync-storage-persister": "5.22.2",
"@tanstack/react-query": "5.22.2",
+ "@tanstack/react-query-devtools": "^5.59.0",
"@tanstack/react-query-persist-client": "5.22.2",
"@wagmi/core": "2.13.3",
"calendar-link": "^2.2.0",
@@ -111,7 +112,7 @@
"@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers@^0.3.0-beta.13",
"@openzeppelin/contracts": "^4.7.3",
"@openzeppelin/test-helpers": "^0.5.16",
- "@playwright/test": "^1.48.0",
+ "@playwright/test": "^1.48.2",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.0.0",
"@testing-library/react-hooks": "^8.0.1",
diff --git a/playwright/pageObjects/profilePage.ts b/playwright/pageObjects/profilePage.ts
index e14abfdba..dcc179fb9 100644
--- a/playwright/pageObjects/profilePage.ts
+++ b/playwright/pageObjects/profilePage.ts
@@ -83,6 +83,11 @@ export class ProfilePage {
return expect(this.page.getByTestId("profile-snippet-person-icon")).toHaveCount(count)
}
+ isPersonhoodErrored(errored = true) {
+ const count = errored ? 1 : 0
+ return expect(this.page.getByTestId("verification-badge-error-icon")).toHaveCount(count)
+ }
+
contentHash(): Locator {
return this.page.getByTestId('other-profile-button-contenthash')
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 07d032c32..4485e22a9 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -150,6 +150,9 @@ importers:
'@tanstack/react-query':
specifier: 5.22.2
version: 5.22.2(react@18.3.1)
+ '@tanstack/react-query-devtools':
+ specifier: ^5.59.0
+ version: 5.59.0(@tanstack/react-query@5.22.2(react@18.3.1))(react@18.3.1)
'@tanstack/react-query-persist-client':
specifier: 5.22.2
version: 5.22.2(@tanstack/react-query@5.22.2(react@18.3.1))(react@18.3.1)
@@ -272,7 +275,7 @@ importers:
specifier: ^0.5.16
version: 0.5.16(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)
'@playwright/test':
- specifier: ^1.48.0
+ specifier: ^1.48.2
version: 1.48.2
'@testing-library/jest-dom':
specifier: ^6.4.2
@@ -3450,12 +3453,21 @@ packages:
'@tanstack/query-core@5.22.2':
resolution: {integrity: sha512-z3PwKFUFACMUqe1eyesCIKg3Jv1mysSrYfrEW5ww5DCDUD4zlpTKBvUDaEjsfZzL3ULrFLDM9yVUxI/fega1Qg==}
+ '@tanstack/query-devtools@5.58.0':
+ resolution: {integrity: sha512-iFdQEFXaYYxqgrv63ots+65FGI+tNp5ZS5PdMU1DWisxk3fez5HG3FyVlbUva+RdYS5hSLbxZ9aw3yEs97GNTw==}
+
'@tanstack/query-persist-client-core@5.22.2':
resolution: {integrity: sha512-sFDgWoN54uclIDIoImPmDzxTq8HhZEt9pO0JbVHjI6LPZqunMMF9yAq9zFKrpH//jD5f+rBCQsdGyhdpUo9e8Q==}
'@tanstack/query-sync-storage-persister@5.22.2':
resolution: {integrity: sha512-mDxXURiMPzWXVc+FwDu94VfIt/uHk5+9EgcxJRYtj8Vsx18T0DiiKk1VgVOBLd97C+Sa7z7ujP2D6Y5lphW+hQ==}
+ '@tanstack/react-query-devtools@5.59.0':
+ resolution: {integrity: sha512-Kz7577FQGU8qmJxROIT/aOwmkTcxfBqgTP6r1AIvuJxVMVHPkp8eQxWQ7BnfBsy/KTJHiV9vMtRVo1+R1tB3vg==}
+ peerDependencies:
+ '@tanstack/react-query': ^5.59.0
+ react: ^18.2.0
+
'@tanstack/react-query-persist-client@5.22.2':
resolution: {integrity: sha512-osAaQn2PDTaa2ApTLOAus7g8Y96LHfS2+Pgu/RoDlEJUEkX7xdEn0YuurxbnJaDJDESMfr+CH/eAX2y+lx02Fg==}
peerDependencies:
@@ -13828,6 +13840,8 @@ snapshots:
'@tanstack/query-core@5.22.2': {}
+ '@tanstack/query-devtools@5.58.0': {}
+
'@tanstack/query-persist-client-core@5.22.2':
dependencies:
'@tanstack/query-core': 5.22.2
@@ -13837,6 +13851,12 @@ snapshots:
'@tanstack/query-core': 5.22.2
'@tanstack/query-persist-client-core': 5.22.2
+ '@tanstack/react-query-devtools@5.59.0(@tanstack/react-query@5.22.2(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@tanstack/query-devtools': 5.58.0
+ '@tanstack/react-query': 5.22.2(react@18.3.1)
+ react: 18.3.1
+
'@tanstack/react-query-persist-client@5.22.2(@tanstack/react-query@5.22.2(react@18.3.1))(react@18.3.1)':
dependencies:
'@tanstack/query-persist-client-core': 5.22.2
diff --git a/src/components/@atoms/PlusMinusControl/PlusMinusControl.tsx b/src/components/@atoms/PlusMinusControl/PlusMinusControl.tsx
index 188bae25b..414f14556 100644
--- a/src/components/@atoms/PlusMinusControl/PlusMinusControl.tsx
+++ b/src/components/@atoms/PlusMinusControl/PlusMinusControl.tsx
@@ -252,7 +252,9 @@ export const PlusMinusControl = forwardRef(
}}
onBlur={handleBlur}
/>
-
+
}
- trailing={
-
- }
+ trailing={}
/>
>
)
diff --git a/src/transaction-flow/input/VerifyProfile/VerifyProfile-flow.tsx b/src/transaction-flow/input/VerifyProfile/VerifyProfile-flow.tsx
index a3fd6eedc..e0f7057e4 100644
--- a/src/transaction-flow/input/VerifyProfile/VerifyProfile-flow.tsx
+++ b/src/transaction-flow/input/VerifyProfile/VerifyProfile-flow.tsx
@@ -32,6 +32,8 @@ const VerifyProfile = ({ data: { name }, dispatch, onDismiss }: Props) => {
const { data: verificationData, isLoading: isVerificationLoading } = useVerifiedRecords({
verificationsRecord: profile?.texts?.find(({ key }) => key === VERIFICATION_RECORD_KEY)?.value,
+ ownerAddress,
+ name,
})
const isLoading = isProfileLoading || isVerificationLoading || isOwnerLoading
diff --git a/src/utils/query/providers.tsx b/src/utils/query/providers.tsx
index 9227d1217..387a4e1ce 100644
--- a/src/utils/query/providers.tsx
+++ b/src/utils/query/providers.tsx
@@ -1,3 +1,4 @@
+import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
import type { ReactNode } from 'react'
import { WagmiProvider } from 'wagmi'
@@ -18,6 +19,7 @@ export function QueryProviders({ children }: Props) {
persistOptions={createPersistConfig({ queryClient })}
>
{children}
+
)
diff --git a/src/utils/query/reactQuery.test.tsx b/src/utils/query/reactQuery.test.tsx
new file mode 100644
index 000000000..5ac7c41da
--- /dev/null
+++ b/src/utils/query/reactQuery.test.tsx
@@ -0,0 +1,143 @@
+import { render, waitFor } from '@app/test-utils'
+
+import { QueryClientProvider } from '@tanstack/react-query'
+import { useQuery } from './useQuery'
+import { PropsWithChildren, ReactNode } from 'react'
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
+import { WagmiProvider } from 'wagmi'
+
+import { queryClient } from './reactQuery'
+import { wagmiConfig } from './wagmi'
+
+const mockFetchData = vi.fn().mockResolvedValue('Test data')
+
+const TestComponentWrapper = ({ children }: { children: ReactNode }) => {
+ return (
+
+ {children}
+
+ )
+}
+
+const TestComponentWithHook = ({ children, ...props }: PropsWithChildren<{}>) => {
+ const { data, isFetching, isLoading } = useQuery({
+ queryKey: ['test-hook'],
+ queryFn: mockFetchData,
+ enabled: true,
+ })
+
+ return (
+
+ {isLoading ? (
+ Loading...
+ ) : (
+
+ Data: {data}
+ {children}
+
+ )}
+
+ )
+}
+
+describe('reactQuery', () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ queryClient.clear()
+ })
+
+ afterEach(() => {
+ queryClient.clear()
+ })
+
+ it('should create a query client with default options', () => {
+ expect(queryClient.getDefaultOptions()).toEqual({
+ queries: {
+ refetchOnMount: true,
+ staleTime: 0,
+ gcTime: 1_000 * 60 * 60 * 24,
+ queryKeyHashFn: expect.any(Function),
+ },
+ })
+ })
+
+ it('should not refetch query on rerender', async () => {
+ const { getByTestId, rerender } = render(
+
+
+ ,
+ )
+
+ await waitFor(() => {
+ expect(mockFetchData).toHaveBeenCalledTimes(1)
+ expect(getByTestId('test')).toHaveTextContent('Test data')
+ })
+
+ rerender(
+
+
+ ,
+ )
+
+ await waitFor(() => {
+ expect(getByTestId('test')).toHaveTextContent('Test data')
+ expect(mockFetchData).toHaveBeenCalledTimes(1)
+ })
+ })
+
+ it('should refetch query on mount', async () => {
+ const { getByTestId, unmount } = render(
+
+
+ ,
+ )
+
+ await waitFor(() => {
+ expect(mockFetchData).toHaveBeenCalledTimes(1)
+ expect(getByTestId('test')).toHaveTextContent('Test data')
+ })
+
+ unmount()
+ const { getByTestId: getByTestId2 } = render(
+
+
+ ,
+ )
+
+ await waitFor(() => {
+ expect(getByTestId2('test')).toHaveTextContent('Test data')
+ expect(mockFetchData).toHaveBeenCalledTimes(2)
+ })
+ })
+
+ it('should fetch twice on nested query with no cache and once with cache', async () => {
+ const { getByTestId, unmount } = render(
+
+
+
+
+ ,
+ )
+
+ await waitFor(() => {
+ expect(getByTestId('test')).toHaveTextContent('Test data')
+ expect(getByTestId('nested')).toHaveTextContent('Test data')
+ expect(mockFetchData).toHaveBeenCalledTimes(2)
+ })
+
+ unmount()
+ const { getByTestId: getByTestId2 } = render(
+
+
+
+
+ ,
+ )
+
+ await waitFor(() => {
+ expect(getByTestId2('test')).toHaveTextContent('Test data')
+ expect(getByTestId2('nested')).toHaveTextContent('Test data')
+ expect(mockFetchData).toHaveBeenCalledTimes(3)
+ })
+ })
+})
diff --git a/src/utils/query/reactQuery.ts b/src/utils/query/reactQuery.ts
index d297288c2..37fd0b132 100644
--- a/src/utils/query/reactQuery.ts
+++ b/src/utils/query/reactQuery.ts
@@ -4,9 +4,8 @@ import { hashFn } from 'wagmi/query'
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
- refetchOnWindowFocus: false,
refetchOnMount: true,
- staleTime: 1_000 * 12,
+ staleTime: 0,
gcTime: 1_000 * 60 * 60 * 24,
queryKeyHashFn: hashFn,
},