diff --git a/packages/wasm-sdk/.gitignore b/packages/wasm-sdk/.gitignore
new file mode 100644
index 00000000000..f2a77e83ec3
--- /dev/null
+++ b/packages/wasm-sdk/.gitignore
@@ -0,0 +1,2 @@
+playwright-report/
+test-results/
\ No newline at end of file
diff --git a/packages/wasm-sdk/index.html b/packages/wasm-sdk/index.html
index 4690923ad45..b4bc1c14737 100644
--- a/packages/wasm-sdk/index.html
+++ b/packages/wasm-sdk/index.html
@@ -1994,6 +1994,7 @@
Results
{ name: "dataContractId", type: "text", label: "Data Contract ID", required: true },
{ name: "documentTypeName", type: "text", label: "Document Type Name", required: true },
{ name: "indexName", type: "text", label: "Index Name", required: true },
+ { name: "indexValues", type: "array", label: "Index Values", required: true },
{ name: "resultType", type: "select", label: "Result Type", required: true,
options: [
{ value: "contenders", label: "Contenders" },
@@ -2014,6 +2015,7 @@ Results
{ name: "dataContractId", type: "text", label: "Data Contract ID", required: true },
{ name: "documentTypeName", type: "text", label: "Document Type Name", required: true },
{ name: "indexName", type: "text", label: "Index Name", required: true },
+ { name: "indexValues", type: "array", label: "Index Values", required: true },
{ name: "contestantId", type: "text", label: "Contestant ID", required: true },
{ name: "startAtIdentifierInfo", type: "json", label: "Start At Identifier Info (JSON)", required: false },
{ name: "count", type: "number", label: "Count", required: false },
@@ -4400,6 +4402,7 @@ Results
values.dataContractId,
values.documentTypeName,
values.indexName,
+ values.indexValues,
values.resultType,
values.allowIncludeLockedAndAbstainingVoteTally,
values.startAtIdentifierInfo ? JSON.stringify(values.startAtIdentifierInfo) : undefined,
@@ -4412,6 +4415,7 @@ Results
values.dataContractId,
values.documentTypeName,
values.indexName,
+ values.indexValues,
values.resultType,
values.allowIncludeLockedAndAbstainingVoteTally,
values.startAtIdentifierInfo ? JSON.stringify(values.startAtIdentifierInfo) : undefined,
@@ -4427,6 +4431,7 @@ Results
values.dataContractId,
values.documentTypeName,
values.indexName,
+ values.indexValues,
values.contestantId,
values.startAtIdentifierInfo ? JSON.stringify(values.startAtIdentifierInfo) : undefined,
values.count,
@@ -4438,6 +4443,7 @@ Results
values.dataContractId,
values.documentTypeName,
values.indexName,
+ values.indexValues,
values.contestantId,
values.startAtIdentifierInfo ? JSON.stringify(values.startAtIdentifierInfo) : undefined,
values.count,
diff --git a/packages/wasm-sdk/test/ui-automation/fixtures/test-data.js b/packages/wasm-sdk/test/ui-automation/fixtures/test-data.js
index 3f5d4f2edfd..f94999c18ad 100644
--- a/packages/wasm-sdk/test/ui-automation/fixtures/test-data.js
+++ b/packages/wasm-sdk/test/ui-automation/fixtures/test-data.js
@@ -247,12 +247,28 @@ const testData = {
},
getTotalCreditsInPlatform: {
testnet: [{}]
+ },
+ getCurrentQuorumsInfo: {
+ testnet: [{}] // No parameters needed
+ },
+ getPrefundedSpecializedBalance: {
+ testnet: [
+ { identityId: "AzaU7zqCT7X1kxh8yWxkT9PxAgNqWDu4Gz13emwcRyAT" }
+ ]
}
},
protocol: {
getProtocolVersionUpgradeState: {
- testnet: [{}]
+ testnet: [{}] // No parameters needed
+ },
+ getProtocolVersionUpgradeVoteStatus: {
+ testnet: [
+ {
+ startProTxHash: "143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113",
+ count: 100
+ }
+ ]
}
},
@@ -263,8 +279,17 @@ const testData = {
getEpochsInfo: {
testnet: [
{
- epoch: 1000,
- count: 5,
+ startEpoch: 1000,
+ count: 100,
+ ascending: true
+ }
+ ]
+ },
+ getFinalizedEpochInfos: {
+ testnet: [
+ {
+ startEpoch: 8635,
+ count: 100,
ascending: true
}
]
@@ -272,9 +297,57 @@ const testData = {
getEvonodesProposedEpochBlocksByIds: {
testnet: [
{
+ epoch: 8635,
ids: ["143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113"]
}
]
+ },
+ getEvonodesProposedEpochBlocksByRange: {
+ testnet: [
+ {
+ epoch: 8635,
+ limit: 10,
+ startAfter: "143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113",
+ orderAscending: true
+ }
+ ]
+ }
+ },
+
+ dpns: {
+ getDpnsUsername: {
+ testnet: [
+ {
+ identityId: "5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk",
+ limit: 10
+ }
+ ]
+ },
+ dpnsCheckAvailability: {
+ testnet: [
+ { label: "alice" },
+ { label: "test-username" },
+ { label: "available-name" }
+ ]
+ },
+ dpnsResolve: {
+ testnet: [
+ { name: "therea1s11mshaddy5" },
+ { name: "alice.dash" },
+ { name: "test-name" }
+ ]
+ },
+ dpnsSearch: {
+ testnet: [
+ {
+ prefix: "the",
+ limit: 10
+ },
+ {
+ prefix: "test",
+ limit: 5
+ }
+ ]
}
},
@@ -282,7 +355,138 @@ const testData = {
getTokenStatuses: {
testnet: [
{
- tokenIds: ["Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv"]
+ tokenIds: ["Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv", "H7FRpZJqZK933r9CzZMsCuf1BM34NT5P2wSJyjDkprqy"]
+ }
+ ]
+ },
+ getTokenDirectPurchasePrices: {
+ testnet: [
+ {
+ tokenIds: ["H7FRpZJqZK933r9CzZMsCuf1BM34NT5P2wSJyjDkprqy"]
+ }
+ ]
+ },
+ getTokenContractInfo: {
+ testnet: [
+ {
+ dataContractId: "H7FRpZJqZK933r9CzZMsCuf1BM34NT5P2wSJyjDkprqy"
+ }
+ ]
+ },
+ getTokenPerpetualDistributionLastClaim: {
+ testnet: [
+ {
+ identityId: "5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk",
+ tokenId: "Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv"
+ }
+ ]
+ },
+ getTokenTotalSupply: {
+ testnet: [
+ {
+ tokenId: "Hqyu8WcRwXCTwbNxdga4CN5gsVEGc67wng4TFzceyLUv"
+ }
+ ]
+ }
+ },
+
+ voting: {
+ getContestedResources: {
+ testnet: [
+ {
+ documentTypeName: "domain",
+ dataContractId: "GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec",
+ indexName: "parentNameAndLabel",
+ resultType: "documents",
+ allowIncludeLockedAndAbstainingVoteTally: false,
+ limit: 10,
+ offset: 0,
+ orderAscending: true
+ }
+ ]
+ },
+ getContestedResourceVoteState: {
+ testnet: [
+ {
+ dataContractId: "GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec",
+ documentTypeName: "domain",
+ indexName: "parentNameAndLabel",
+ indexValues: ["dash", "alice"],
+ resultType: "contenders",
+ allowIncludeLockedAndAbstainingVoteTally: false,
+ count: 10,
+ orderAscending: true
+ }
+ ]
+ },
+ getContestedResourceVotersForIdentity: {
+ testnet: [
+ {
+ dataContractId: "GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec",
+ documentTypeName: "domain",
+ indexName: "parentNameAndLabel",
+ indexValues: ["dash", "alice"],
+ contestantId: "5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk",
+ count: 10,
+ orderAscending: true
+ }
+ ]
+ },
+ getContestedResourceIdentityVotes: {
+ testnet: [
+ {
+ identityId: "5DbLwAxGBzUzo81VewMUwn4b5P4bpv9FNFybi25XB5Bk",
+ limit: 10,
+ offset: 0,
+ orderAscending: true
+ }
+ ]
+ },
+ getVotePollsByEndDate: {
+ testnet: [
+ {
+ limit: 10,
+ offset: 0,
+ orderAscending: true
+ }
+ ]
+ }
+ },
+
+ group: {
+ getGroupInfo: {
+ testnet: [
+ {
+ contractId: "49PJEnNx7ReCitzkLdkDNr4s6RScGsnNexcdSZJ1ph5N",
+ groupContractPosition: 0
+ }
+ ]
+ },
+ getGroupInfos: {
+ testnet: [
+ {
+ contractId: "49PJEnNx7ReCitzkLdkDNr4s6RScGsnNexcdSZJ1ph5N",
+ count: 100
+ }
+ ]
+ },
+ getGroupActions: {
+ testnet: [
+ {
+ contractId: "49PJEnNx7ReCitzkLdkDNr4s6RScGsnNexcdSZJ1ph5N",
+ groupContractPosition: 0,
+ status: "ACTIVE",
+ count: 10
+ }
+ ]
+ },
+ getGroupActionSigners: {
+ testnet: [
+ {
+ contractId: "49PJEnNx7ReCitzkLdkDNr4s6RScGsnNexcdSZJ1ph5N",
+ groupContractPosition: 0,
+ status: "ACTIVE",
+ actionId: "6XJzL6Qb8Zhwxt4HFwh8NAn7q1u4dwdoUf8EmgzDudFZ"
}
]
}
diff --git a/packages/wasm-sdk/test/ui-automation/tests/query-execution.spec.js b/packages/wasm-sdk/test/ui-automation/tests/query-execution.spec.js
index dfb5c582564..4cc8d7661e3 100644
--- a/packages/wasm-sdk/test/ui-automation/tests/query-execution.spec.js
+++ b/packages/wasm-sdk/test/ui-automation/tests/query-execution.spec.js
@@ -80,6 +80,19 @@ function validateBasicQueryResult(result) {
expect(result.result).not.toContain('invalid');
}
+/**
+ * Helper function to validate basic query result properties for DPNS queries
+ * (allows "not found" as valid response)
+ * @param {Object} result - The query result object
+ */
+function validateBasicDpnsQueryResult(result) {
+ expect(result.success).toBe(true);
+ expect(result.result).toBeDefined();
+ expect(result.hasError).toBe(false);
+ expect(result.result).not.toContain('Error executing query');
+ expect(result.result).not.toContain('invalid');
+}
+
/**
* Helper function to validate proof content contains expected fields
* @param {string} proofContent - The proof content string
@@ -137,8 +150,14 @@ function validateDocumentResult(resultStr) {
// Documents can be arrays or single objects
if (Array.isArray(documentData)) {
expect(documentData.length).toBeGreaterThanOrEqual(0);
+ // Validate each document in the array has ownerId
+ documentData.forEach(document => {
+ expect(document).toHaveProperty('ownerId');
+ });
} else {
expect(documentData).toBeInstanceOf(Object);
+ // Validate single document has ownerId
+ expect(documentData).toHaveProperty('ownerId');
}
}
@@ -170,6 +189,10 @@ function validateKeysResult(resultStr) {
expect(() => JSON.parse(resultStr)).not.toThrow();
const keysData = JSON.parse(resultStr);
expect(keysData).toBeDefined();
+ keysData.forEach(key => {
+ expect(key).toHaveProperty('keyId')
+ expect(key).toHaveProperty('purpose')
+ });
}
function validateIdentitiesResult(resultStr) {
@@ -195,6 +218,10 @@ function validateBalancesResult(resultStr) {
expect(balancesData).toBeDefined();
if (Array.isArray(balancesData)) {
expect(balancesData.length).toBeGreaterThanOrEqual(0);
+ // Validate each balance object in the array
+ balancesData.forEach(balanceObj => {
+ expect(balanceObj).toHaveProperty('balance');
+ });
}
}
@@ -203,18 +230,26 @@ function validateBalanceAndRevisionResult(resultStr) {
const data = JSON.parse(resultStr);
expect(data).toBeDefined();
expect(data).toBeInstanceOf(Object);
+ expect(data).toHaveProperty('balance');
+ expect(data).toHaveProperty('revision');
}
function validateTokenBalanceResult(resultStr) {
expect(() => JSON.parse(resultStr)).not.toThrow();
const tokenData = JSON.parse(resultStr);
expect(tokenData).toBeDefined();
+ tokenData.forEach(token => {
+ expect(token).toHaveProperty('balance');
+ });
}
function validateTokenInfoResult(resultStr) {
expect(() => JSON.parse(resultStr)).not.toThrow();
const tokenInfoData = JSON.parse(resultStr);
expect(tokenInfoData).toBeDefined();
+ tokenInfoData.forEach(token => {
+ expect(token).toHaveProperty('isFrozen');
+ });
}
test.describe('WASM SDK Query Execution Tests', () => {
@@ -260,6 +295,13 @@ test.describe('WASM SDK Query Execution Tests', () => {
expect(() => JSON.parse(result.result)).not.toThrow();
const contractsData = JSON.parse(result.result);
expect(contractsData).toBeDefined();
+ expect(contractsData).toHaveProperty('dataContracts');
+ expect(typeof contractsData.dataContracts).toBe('object');
+
+ // Validate each contract using validateContractResult
+ Object.values(contractsData.dataContracts).forEach(contract => {
+ validateContractResult(JSON.stringify(contract));
+ });
console.log('✅ getDataContracts single view without proof confirmed');
});
@@ -323,6 +365,13 @@ test.describe('WASM SDK Query Execution Tests', () => {
expect(() => JSON.parse(result.result)).not.toThrow();
const contractsData = JSON.parse(result.result);
expect(contractsData).toBeDefined();
+ expect(contractsData).toHaveProperty('dataContracts');
+ expect(typeof contractsData.dataContracts).toBe('object');
+
+ // Validate each contract using validateContractResult
+ Object.values(contractsData.dataContracts).forEach(contract => {
+ validateContractResult(JSON.stringify(contract));
+ });
// If proof was enabled, verify split view
if (proofEnabled) {
@@ -440,55 +489,520 @@ test.describe('WASM SDK Query Execution Tests', () => {
});
test.describe('System Queries', () => {
- test('should execute getStatus query', async () => {
- await wasmSdkPage.setupQuery('system', 'getStatus');
-
- // Status query needs no parameters
- const result = await wasmSdkPage.executeQueryAndGetResult();
-
- // Status should generally succeed
- expect(result.success).toBe(true);
- expect(result.result).toBeDefined();
- expect(result.result).toContain('version');
-
+ const systemQueries = [
+ {
+ name: 'getStatus',
+ hasProofSupport: false, // No proof function in WASM-SDK
+ needsParameters: false,
+ validateFn: (result) => {
+ expect(result).toBeDefined();
+ expect(result).toContain('version');
+ }
+ },
+ {
+ name: 'getTotalCreditsInPlatform',
+ hasProofSupport: true,
+ needsParameters: false,
+ validateFn: (result) => {
+ expect(result).toBeDefined();
+ expect(result).toMatch(/\d+|credits|balance/i);
+ }
+ },
+ {
+ name: 'getCurrentQuorumsInfo',
+ hasProofSupport: false, // No proof function in WASM-SDK
+ needsParameters: false,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const quorumsData = JSON.parse(result);
+ expect(quorumsData).toBeDefined();
+ expect(quorumsData).toHaveProperty('quorums');
+ expect(Array.isArray(quorumsData.quorums)).toBe(true);
+ }
+ },
+ {
+ name: 'getPrefundedSpecializedBalance',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const balanceData = JSON.parse(result);
+ expect(balanceData).toBeDefined();
+ expect(balanceData).toHaveProperty('identityId');
+ expect(balanceData).toHaveProperty('balance');
+ }
+ }
+ ];
+
+ systemQueries.forEach(({ name, hasProofSupport, needsParameters, validateFn }) => {
+ test.describe(`${name} query (parameterized)`, () => {
+ test('without proof info', async () => {
+ await wasmSdkPage.setupQuery('system', name);
+
+ if (needsParameters) {
+ const success = await parameterInjector.injectParameters('system', name, 'testnet');
+ expect(success).toBe(true);
+ }
+
+ const result = await wasmSdkPage.executeQueryAndGetResult();
+ validateBasicQueryResult(result);
+ validateSingleView(result);
+ validateFn(result.result);
+
+ console.log(`✅ ${name} single view without proof confirmed`);
+ });
+
+ if (hasProofSupport) {
+ test('with proof info', async () => {
+ const { result, proofEnabled } = await executeQueryWithProof(
+ wasmSdkPage,
+ parameterInjector,
+ 'system',
+ name,
+ 'testnet'
+ );
+
+ validateBasicQueryResult(result);
+
+ if (proofEnabled) {
+ validateSplitView(result);
+ console.log(`✅ ${name} split view with proof confirmed`);
+ } else {
+ console.log(`⚠️ Proof was not enabled for ${name} query`);
+ }
+
+ validateFn(result.result);
+ });
+ } else {
+ test.skip('with proof info', async () => {
+ // Proof support not yet implemented for this query
+ });
+ }
+ });
});
+ });
- test('should execute getCurrentEpoch query', async () => {
- await wasmSdkPage.setupQuery('epoch', 'getCurrentEpoch');
-
- const result = await wasmSdkPage.executeQueryAndGetResult();
-
- // Verify query executed successfully
- expect(result.success).toBe(true);
- expect(result.result).toBeDefined();
-
- // Verify the result is not an error message
- expect(result.hasError).toBe(false);
- expect(result.result).not.toContain('Error executing query');
- expect(result.result).not.toContain('not found');
-
- // Should contain epoch data (number or JSON with epoch info)
- expect(result.result).toMatch(/\d+|epoch/i);
-
+ test.describe('Epoch & Block Queries', () => {
+ const epochQueries = [
+ {
+ name: 'getCurrentEpoch',
+ hasProofSupport: true,
+ needsParameters: false,
+ validateFn: (result) => {
+ expect(result).toBeDefined();
+ expect(result).toMatch(/\d+|epoch/i);
+ }
+ },
+ {
+ name: 'getEpochsInfo',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const epochData = JSON.parse(result);
+ expect(epochData).toBeDefined();
+ expect(typeof epochData === 'object').toBe(true);
+ }
+ },
+ {
+ name: 'getFinalizedEpochInfos',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const epochData = JSON.parse(result);
+ expect(epochData).toBeDefined();
+ expect(typeof epochData === 'object').toBe(true);
+ }
+ },
+ {
+ name: 'getEvonodesProposedEpochBlocksByIds',
+ hasProofSupport: false, // Proof support not yet implemented in WASM-SDK
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const blockData = JSON.parse(result);
+ expect(blockData).toBeDefined();
+ expect(typeof blockData === 'object').toBe(true);
+ }
+ },
+ {
+ name: 'getEvonodesProposedEpochBlocksByRange',
+ hasProofSupport: false, // Proof support not yet implemented in WASM-SDK
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const blockData = JSON.parse(result);
+ expect(blockData).toBeDefined();
+ expect(typeof blockData === 'object').toBe(true);
+ }
+ }
+ ];
+
+ epochQueries.forEach(({ name, hasProofSupport, needsParameters, validateFn }) => {
+ test.describe(`${name} query (parameterized)`, () => {
+ test('without proof info', async () => {
+ await wasmSdkPage.setupQuery('epoch', name);
+
+ if (needsParameters) {
+ const success = await parameterInjector.injectParameters('epoch', name, 'testnet');
+ expect(success).toBe(true);
+ }
+
+ const result = await wasmSdkPage.executeQueryAndGetResult();
+ validateBasicQueryResult(result);
+ validateSingleView(result);
+ validateFn(result.result);
+
+ console.log(`✅ ${name} single view without proof confirmed`);
+ });
+
+ if (hasProofSupport) {
+ test('with proof info', async () => {
+ const { result, proofEnabled } = await executeQueryWithProof(
+ wasmSdkPage,
+ parameterInjector,
+ 'epoch',
+ name,
+ 'testnet'
+ );
+
+ validateBasicQueryResult(result);
+
+ if (proofEnabled) {
+ validateSplitView(result);
+ console.log(`✅ ${name} split view with proof confirmed`);
+ } else {
+ console.log(`⚠️ Proof was not enabled for ${name} query`);
+ }
+
+ validateFn(result.result);
+ });
+ } else {
+ test.skip('with proof info', async () => {
+ // Proof support not yet implemented for this query
+ });
+ }
+ });
});
+ });
- test('should execute getTotalCreditsInPlatform query', async () => {
- await wasmSdkPage.setupQuery('system', 'getTotalCreditsInPlatform');
-
- const result = await wasmSdkPage.executeQueryAndGetResult();
-
- // Verify query executed successfully
- expect(result.success).toBe(true);
- expect(result.result).toBeDefined();
-
- // Verify the result is not an error message
- expect(result.hasError).toBe(false);
- expect(result.result).not.toContain('Error executing query');
- expect(result.result).not.toContain('not found');
-
- // Should contain credits data (number or JSON with credits info)
- expect(result.result).toMatch(/\d+|credits|balance/i);
-
+ test.describe('Token Queries', () => {
+ const tokenQueries = [
+ {
+ name: 'getTokenStatuses',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const tokenStatuses = JSON.parse(result);
+ expect(tokenStatuses).toBeDefined();
+ expect(Array.isArray(tokenStatuses)).toBe(true);
+ tokenStatuses.forEach(token => {
+ expect(token).toHaveProperty('isPaused');
+ expect(typeof token.isPaused).toBe('boolean');
+ });
+ }
+ },
+ {
+ name: 'getTokenDirectPurchasePrices',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const priceData = JSON.parse(result);
+ expect(priceData).toBeDefined();
+ expect(Array.isArray(priceData)).toBe(true);
+ priceData.forEach(token => {
+ expect(token).toHaveProperty('basePrice');
+ });
+ }
+ },
+ {
+ name: 'getTokenContractInfo',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const contractInfo = JSON.parse(result);
+ expect(contractInfo).toBeDefined();
+ expect(typeof contractInfo === 'object').toBe(true);
+ expect(contractInfo).toHaveProperty('contractId');
+ }
+ },
+ {
+ name: 'getTokenPerpetualDistributionLastClaim',
+ hasProofSupport: false,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const claimData = JSON.parse(result);
+ expect(claimData).toBeDefined();
+ expect(typeof claimData === 'object').toBe(true);
+ }
+ },
+ {
+ name: 'getTokenTotalSupply',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const supplyData = JSON.parse(result);
+ expect(supplyData).toBeDefined();
+ expect(typeof supplyData === 'object').toBe(true);
+ expect(supplyData).toHaveProperty('totalSupply');
+ }
+ }
+ ];
+
+ tokenQueries.forEach(({ name, hasProofSupport, needsParameters, validateFn }) => {
+ test.describe(`${name} query (parameterized)`, () => {
+ test('without proof info', async () => {
+ await wasmSdkPage.setupQuery('token', name);
+
+ if (needsParameters) {
+ const success = await parameterInjector.injectParameters('token', name, 'testnet');
+ expect(success).toBe(true);
+ }
+
+ const result = await wasmSdkPage.executeQueryAndGetResult();
+ validateBasicQueryResult(result);
+ validateSingleView(result);
+ validateFn(result.result);
+
+ console.log(`✅ ${name} single view without proof confirmed`);
+ });
+
+ if (hasProofSupport) {
+ test('with proof info', async () => {
+ const { result, proofEnabled } = await executeQueryWithProof(
+ wasmSdkPage,
+ parameterInjector,
+ 'token',
+ name,
+ 'testnet'
+ );
+
+ validateBasicQueryResult(result);
+
+ if (proofEnabled) {
+ validateSplitView(result);
+ console.log(`✅ ${name} split view with proof confirmed`);
+ } else {
+ console.log(`⚠️ Proof was not enabled for ${name} query`);
+ }
+
+ validateFn(result.result);
+ });
+ } else {
+ test.skip('with proof info', async () => {
+ // Proof support not yet implemented for this query
+ });
+ }
+ });
+ });
+ });
+
+ test.describe('Voting & Contested Resources Queries', () => {
+ const votingQueries = [
+ {
+ name: 'getContestedResources',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const contestedData = JSON.parse(result);
+ expect(contestedData).toBeDefined();
+ expect(typeof contestedData === 'object').toBe(true);
+ }
+ },
+ {
+ name: 'getContestedResourceVoteState',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const voteStateData = JSON.parse(result);
+ expect(voteStateData).toBeDefined();
+ expect(typeof voteStateData === 'object').toBe(true);
+ }
+ },
+ {
+ name: 'getContestedResourceVotersForIdentity',
+ hasProofSupport: false, // Not working
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const votersData = JSON.parse(result);
+ expect(votersData).toBeDefined();
+ expect(typeof votersData === 'object').toBe(true);
+ }
+ },
+ {
+ name: 'getContestedResourceIdentityVotes',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const identityVotesData = JSON.parse(result);
+ expect(identityVotesData).toBeDefined();
+ expect(typeof identityVotesData === 'object').toBe(true);
+ }
+ },
+ {
+ name: 'getVotePollsByEndDate',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const pollsData = JSON.parse(result);
+ expect(pollsData).toBeDefined();
+ expect(typeof pollsData === 'object').toBe(true);
+ }
+ }
+ ];
+
+ votingQueries.forEach(({ name, hasProofSupport, needsParameters, validateFn }) => {
+ test.describe(`${name} query (parameterized)`, () => {
+ test('without proof info', async () => {
+ await wasmSdkPage.setupQuery('voting', name);
+
+ if (needsParameters) {
+ const success = await parameterInjector.injectParameters('voting', name, 'testnet');
+ expect(success).toBe(true);
+ }
+
+ const result = await wasmSdkPage.executeQueryAndGetResult();
+ validateBasicQueryResult(result);
+ validateSingleView(result);
+ validateFn(result.result);
+
+ console.log(`✅ ${name} single view without proof confirmed`);
+ });
+
+ if (hasProofSupport) {
+ test('with proof info', async () => {
+ const { result, proofEnabled } = await executeQueryWithProof(
+ wasmSdkPage,
+ parameterInjector,
+ 'voting',
+ name,
+ 'testnet'
+ );
+
+ validateBasicQueryResult(result);
+
+ if (proofEnabled) {
+ validateSplitView(result);
+ console.log(`✅ ${name} split view with proof confirmed`);
+ } else {
+ console.log(`⚠️ Proof was not enabled for ${name} query`);
+ }
+
+ validateFn(result.result);
+ });
+ } else {
+ test.skip('with proof info', async () => {
+ // Proof support not yet implemented for this query
+ });
+ }
+ });
+ });
+ });
+
+ test.describe('Group Queries', () => {
+ const groupQueries = [
+ {
+ name: 'getGroupInfo',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const groupInfo = JSON.parse(result);
+ expect(groupInfo).toBeDefined();
+ expect(typeof groupInfo === 'object').toBe(true);
+ }
+ },
+ {
+ name: 'getGroupInfos',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const groupInfos = JSON.parse(result);
+ expect(groupInfos).toBeDefined();
+ expect(typeof groupInfos === 'object').toBe(true);
+ }
+ },
+ {
+ name: 'getGroupActions',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const groupActions = JSON.parse(result);
+ expect(groupActions).toBeDefined();
+ expect(typeof groupActions === 'object').toBe(true);
+ }
+ },
+ {
+ name: 'getGroupActionSigners',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const actionSigners = JSON.parse(result);
+ expect(actionSigners).toBeDefined();
+ expect(typeof actionSigners === 'object').toBe(true);
+ }
+ }
+ ];
+
+ groupQueries.forEach(({ name, hasProofSupport, needsParameters, validateFn }) => {
+ test.describe(`${name} query (parameterized)`, () => {
+ test('without proof info', async () => {
+ await wasmSdkPage.setupQuery('group', name);
+
+ if (needsParameters) {
+ const success = await parameterInjector.injectParameters('group', name, 'testnet');
+ expect(success).toBe(true);
+ }
+
+ const result = await wasmSdkPage.executeQueryAndGetResult();
+ validateBasicQueryResult(result);
+ validateSingleView(result);
+ validateFn(result.result);
+
+ console.log(`✅ ${name} single view without proof confirmed`);
+ });
+
+ if (hasProofSupport) {
+ test('with proof info', async () => {
+ const { result, proofEnabled } = await executeQueryWithProof(
+ wasmSdkPage,
+ parameterInjector,
+ 'group',
+ name,
+ 'testnet'
+ );
+
+ validateBasicQueryResult(result);
+
+ if (proofEnabled) {
+ validateSplitView(result);
+ console.log(`✅ ${name} split view with proof confirmed`);
+ } else {
+ console.log(`⚠️ Proof was not enabled for ${name} query`);
+ }
+
+ validateFn(result.result);
+ });
+ } else {
+ test.skip('with proof info', async () => {
+ // Proof support not yet implemented for this query
+ });
+ }
+ });
});
});
@@ -566,6 +1080,184 @@ test.describe('WASM SDK Query Execution Tests', () => {
});
});
+ test.describe('Protocol & Version Queries', () => {
+ const protocolQueries = [
+ {
+ name: 'getProtocolVersionUpgradeState',
+ hasProofSupport: true,
+ needsParameters: false,
+ validateFn: (result) => {
+ expect(result).toBeDefined();
+ expect(result).toContain('currentProtocolVersion');
+ }
+ },
+ {
+ name: 'getProtocolVersionUpgradeVoteStatus',
+ hasProofSupport: false, // Proof support not yet implemented in WASM-SDK
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const voteData = JSON.parse(result);
+ expect(voteData).toBeDefined();
+ expect(typeof voteData === 'object').toBe(true);
+ }
+ }
+ ];
+
+ protocolQueries.forEach(({ name, hasProofSupport, needsParameters, validateFn }) => {
+ test.describe(`${name} query (parameterized)`, () => {
+ test('without proof info', async () => {
+ await wasmSdkPage.setupQuery('protocol', name);
+
+ if (needsParameters) {
+ const success = await parameterInjector.injectParameters('protocol', name, 'testnet');
+ expect(success).toBe(true);
+ }
+
+ const result = await wasmSdkPage.executeQueryAndGetResult();
+ validateBasicQueryResult(result);
+ validateSingleView(result);
+ validateFn(result.result);
+
+ console.log(`✅ ${name} single view without proof confirmed`);
+ });
+
+ if (hasProofSupport) {
+ test('with proof info', async () => {
+ const { result, proofEnabled } = await executeQueryWithProof(
+ wasmSdkPage,
+ parameterInjector,
+ 'protocol',
+ name,
+ 'testnet'
+ );
+
+ validateBasicQueryResult(result);
+
+ if (proofEnabled) {
+ validateSplitView(result);
+ console.log(`✅ ${name} split view with proof confirmed`);
+ } else {
+ console.log(`⚠️ Proof was not enabled for ${name} query`);
+ }
+
+ validateFn(result.result);
+ });
+ } else {
+ test.skip('with proof info', async () => {
+ // Proof support not yet implemented for this query
+ });
+ }
+ });
+ });
+ });
+
+ test.describe('DPNS Queries', () => {
+ const dpnsQueries = [
+ {
+ name: 'getDpnsUsername',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const usernameData = JSON.parse(result);
+ expect(usernameData).toBeDefined();
+ if (Array.isArray(usernameData)) {
+ expect(usernameData.length).toBeGreaterThanOrEqual(1);
+ }
+ }
+ },
+ {
+ name: 'dpnsCheckAvailability',
+ hasProofSupport: false, // Proof support not yet implemented in WASM-SDK
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const availabilityData = JSON.parse(result);
+ expect(availabilityData).toBeDefined();
+ expect(typeof availabilityData === 'boolean' || typeof availabilityData === 'object').toBe(true);
+ }
+ },
+ {
+ name: 'dpnsResolve',
+ hasProofSupport: false, // Proof support not yet implemented in WASM-SDK
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const resolveData = JSON.parse(result);
+ // Check for either successful resolution (has name) or error response
+ if (resolveData && typeof resolveData === 'object') {
+ // Valid response structure - may or may not have 'name' depending on resolution success
+ expect(resolveData).toBeDefined();
+ }
+ }
+ },
+ {
+ name: 'dpnsSearch',
+ hasProofSupport: true,
+ needsParameters: true,
+ validateFn: (result) => {
+ expect(() => JSON.parse(result)).not.toThrow();
+ const searchData = JSON.parse(result);
+ expect(searchData).toBeDefined();
+ if (Array.isArray(searchData)) {
+ expect(searchData.length).toBeGreaterThanOrEqual(0);
+ searchData.forEach(result => {
+ expect(result).toHaveProperty('username');
+ });
+ }
+ }
+ }
+ ];
+
+ dpnsQueries.forEach(({ name, hasProofSupport, needsParameters, validateFn }) => {
+ test.describe(`${name} query (parameterized)`, () => {
+ test('without proof info', async () => {
+ await wasmSdkPage.setupQuery('dpns', name);
+
+ if (needsParameters) {
+ const success = await parameterInjector.injectParameters('dpns', name, 'testnet');
+ expect(success).toBe(true);
+ }
+
+ const result = await wasmSdkPage.executeQueryAndGetResult();
+ validateBasicDpnsQueryResult(result);
+ validateSingleView(result);
+ validateFn(result.result);
+
+ console.log(`✅ ${name} single view without proof confirmed`);
+ });
+
+ if (hasProofSupport) {
+ test('with proof info', async () => {
+ const { result, proofEnabled } = await executeQueryWithProof(
+ wasmSdkPage,
+ parameterInjector,
+ 'dpns',
+ name,
+ 'testnet'
+ );
+
+ validateBasicDpnsQueryResult(result);
+
+ if (proofEnabled) {
+ validateSplitView(result);
+ console.log(`✅ ${name} split view with proof confirmed`);
+ } else {
+ console.log(`⚠️ Proof was not enabled for ${name} query`);
+ }
+
+ validateFn(result.result);
+ });
+ } else {
+ test.skip('with proof info', async () => {
+ // Proof support not yet implemented for this query
+ });
+ }
+ });
+ });
+ });
+
// Test Identity Queries
test.describe('Identity Queries', () => {
// Complete set of all available identity queries with correct proof support
diff --git a/packages/wasm-sdk/test/ui-automation/utils/base-test.js b/packages/wasm-sdk/test/ui-automation/utils/base-test.js
index 9ed39f08d76..23034fb2694 100644
--- a/packages/wasm-sdk/test/ui-automation/utils/base-test.js
+++ b/packages/wasm-sdk/test/ui-automation/utils/base-test.js
@@ -214,16 +214,32 @@ class BaseTest {
// Click execute button
await executeButton.click();
- // Wait for status banner to show loading
- await this.page.locator('#statusBanner.loading').waitFor({ state: 'visible' });
+ const statusBanner = this.page.locator('#statusBanner');
- // Wait for loading to complete (either success or error)
- await this.page.locator('#statusBanner.loading').waitFor({ state: 'hidden', timeout: 30000 });
+ // Try waiting for loading state, but handle queries that execute instantly
+ try {
+ // Wait for status banner to show loading
+ await this.page.locator('#statusBanner.loading').waitFor({ state: 'visible', timeout: 5000 });
+
+ // Wait for loading to complete (either success or error)
+ await this.page.locator('#statusBanner.loading').waitFor({ state: 'hidden', timeout: 30000 });
+ } catch (error) {
+ // Some queries execute so quickly they never show loading state
+ // Check if the query already completed successfully or with an error
+ const currentStatus = await statusBanner.getAttribute('class');
+ if (currentStatus && (currentStatus.includes('success') || currentStatus.includes('error'))) {
+ // Query completed without showing loading state - this is okay for fast queries
+ console.log('Query executed');
+ return currentStatus.includes('success');
+ }
+
+ // If not in a final state, re-throw the timeout error
+ throw error;
+ }
console.log('Query executed');
// Return whether it was successful
- const statusBanner = this.page.locator('#statusBanner');
const statusClass = await statusBanner.getAttribute('class');
return statusClass && statusClass.includes('success');
}
diff --git a/packages/wasm-sdk/test/ui-automation/utils/parameter-injector.js b/packages/wasm-sdk/test/ui-automation/utils/parameter-injector.js
index aa1f555c85e..4b97e6fafea 100644
--- a/packages/wasm-sdk/test/ui-automation/utils/parameter-injector.js
+++ b/packages/wasm-sdk/test/ui-automation/utils/parameter-injector.js
@@ -40,7 +40,7 @@ class ParameterInjector {
return {
// Identity parameters
'id': ['#id', '[name="id"]', 'input[placeholder*="Identity ID"]'],
- 'identityId': ['#identityId', '[name="identityId"]', 'input[placeholder*="Identity ID"]'],
+ 'identityId': ['[name="identityId"]', '#identityId', 'input[placeholder*="Identity ID"]'],
'identityIds': ['input[placeholder="Enter value"]', '.array-input-container input[type="text"]', '[data-array-name="identityIds"] input[type="text"]', '.array-input-container[data-array-name="identityIds"] input', '#identityIds', '[name="identityIds"]', 'input[placeholder*="Identity IDs"]'],
'identitiesIds': ['input[placeholder="Enter value"]', '.array-input-container input[type="text"]', '[data-array-name="identitiesIds"] input[type="text"]', '.array-input-container[data-array-name="identitiesIds"] input', '#identitiesIds', '[name="identitiesIds"]', 'input[placeholder*="Identity IDs"]'],
@@ -62,6 +62,11 @@ class ParameterInjector {
'tokenId': ['#tokenId', '[name="tokenId"]', 'input[placeholder*="Token ID"]'],
'tokenIds': ['input[placeholder="Enter value"]', '.array-input-container input[type="text"]', '[data-array-name="tokenIds"] input[type="text"]', '.array-input-container[data-array-name="tokenIds"] input', '#tokenIds', '[name="tokenIds"]', 'input[placeholder*="Token IDs"]'],
+ // DPNS parameters
+ 'label': ['#label', '[name="label"]', 'input[placeholder*="Username"]', 'input[placeholder*="Label"]'],
+ 'name': ['#name', '[name="name"]', 'input[placeholder*="Name"]', 'input[placeholder*="DPNS"]'],
+ 'prefix': ['#prefix', '[name="prefix"]', 'input[placeholder*="prefix"]', 'input[placeholder*="Prefix"]'],
+
// Query modifiers
'limit': ['#limit', '[name="limit"]', 'input[placeholder*="limit" i]'],
'offset': ['#offset', '[name="offset"]', 'input[placeholder*="offset" i]'],
@@ -71,6 +76,8 @@ class ParameterInjector {
'epoch': ['#epoch', '[name="epoch"]', 'input[placeholder*="epoch" i]'],
'startEpoch': ['#startEpoch', '[name="startEpoch"]'],
'ascending': ['#ascending', '[name="ascending"]', 'input[type="checkbox"][name="ascending"]'],
+ 'orderAscending': ['#orderAscending', '[name="orderAscending"]', 'input[type="checkbox"][name="orderAscending"]'],
+ 'startAfter': ['#startAfter', '[name="startAfter"]', 'input[placeholder*="startAfter" i]'],
// ProTx parameters
'startProTxHash': ['#startProTxHash', '[name="startProTxHash"]'],
@@ -83,8 +90,21 @@ class ParameterInjector {
// Voting parameters
'documentTypeName': ['#documentTypeName', '[name="documentTypeName"]'],
'indexName': ['#indexName', '[name="indexName"]'],
+ 'indexValues': ['#indexValues', '[name="indexValues"]', 'textarea[name="indexValues"]', 'input[placeholder*="indexValues"]'],
'resultType': ['#resultType', '[name="resultType"]'],
'contestantId': ['#contestantId', '[name="contestantId"]'],
+ 'allowIncludeLockedAndAbstainingVoteTally': ['#allowIncludeLockedAndAbstainingVoteTally', '[name="allowIncludeLockedAndAbstainingVoteTally"]', 'input[type="checkbox"][name="allowIncludeLockedAndAbstainingVoteTally"]'],
+ 'startAtIdentifierInfo': ['#startAtIdentifierInfo', '[name="startAtIdentifierInfo"]'],
+
+ // Group parameters
+ 'contractId': ['#contractId', '[name="contractId"]', 'input[placeholder*="Contract ID"]'],
+ 'groupContractPosition': ['#groupContractPosition', '[name="groupContractPosition"]'],
+ 'startAtGroupContractPosition': ['#startAtGroupContractPosition', '[name="startAtGroupContractPosition"]'],
+ 'startGroupContractPositionIncluded': ['#startGroupContractPositionIncluded', '[name="startGroupContractPositionIncluded"]', 'input[type="checkbox"][name="startGroupContractPositionIncluded"]'],
+ 'status': ['#status', '[name="status"]', 'select[name="status"]'],
+ 'actionId': ['#actionId', '[name="actionId"]'],
+ 'startActionId': ['#startActionId', '[name="startActionId"]'],
+ 'startActionIdIncluded': ['#startActionIdIncluded', '[name="startActionIdIncluded"]', 'input[type="checkbox"][name="startActionIdIncluded"]'],
// Time parameters
'startTimeMs': ['#startTimeMs', '[name="startTimeMs"]'],
diff --git a/packages/wasm-sdk/test/ui-automation/utils/wasm-sdk-page.js b/packages/wasm-sdk/test/ui-automation/utils/wasm-sdk-page.js
index de2fa8ef93b..0bddb309823 100644
--- a/packages/wasm-sdk/test/ui-automation/utils/wasm-sdk-page.js
+++ b/packages/wasm-sdk/test/ui-automation/utils/wasm-sdk-page.js
@@ -6,7 +6,8 @@ const DYNAMIC_ARRAY_PARAMETERS = {
'ids': true,
'identityIds': true,
'identitiesIds': true,
- 'tokenIds': true
+ 'tokenIds': true,
+ 'indexValues': true
};
/**