diff --git a/govtool/frontend/package-lock.json b/govtool/frontend/package-lock.json index 4b27d06fd..5a5a89014 100644 --- a/govtool/frontend/package-lock.json +++ b/govtool/frontend/package-lock.json @@ -14,7 +14,7 @@ "@emurgo/cardano-serialization-lib-asmjs": "12.0.0-alpha.29", "@hookform/resolvers": "^3.3.1", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "^0.2.7", + "@intersect.mbo/pdf-ui": "^0.2.8", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", @@ -3210,9 +3210,9 @@ "license": "ISC" }, "node_modules/@intersect.mbo/pdf-ui": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.2.7.tgz", - "integrity": "sha512-vYmxs2F5Grk0Np/DfcytaXiPfgP8YWUYTKoWriS1DWSUdKZgj27DYQbPIL3dRjUW6kOC7rFDdbNQR9bZJ2YVkw==", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.2.8.tgz", + "integrity": "sha512-ioksMZ3G5PJ1RCZPJb5Ui6lKz6bgSk5R5HbjTCY1+AQIDjLIlYE0+gslwqxl1NDF6pLevJUGX+TZAXJgYUd6Vg==", "dependencies": { "@fontsource/poppins": "^5.0.14", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", diff --git a/govtool/frontend/package.json b/govtool/frontend/package.json index 59e7ad9a1..5b6630ad7 100644 --- a/govtool/frontend/package.json +++ b/govtool/frontend/package.json @@ -28,7 +28,7 @@ "@emurgo/cardano-serialization-lib-asmjs": "12.0.0-alpha.29", "@hookform/resolvers": "^3.3.1", "@intersect.mbo/intersectmbo.org-icons-set": "^1.0.8", - "@intersect.mbo/pdf-ui": "^0.2.7", + "@intersect.mbo/pdf-ui": "^0.2.8", "@mui/icons-material": "^5.14.3", "@mui/material": "^5.14.4", "@rollup/plugin-babel": "^6.0.4", diff --git a/govtool/frontend/src/components/organisms/DashboardCards/ProposeGovActionDashboardCard.tsx b/govtool/frontend/src/components/organisms/DashboardCards/ProposeGovActionDashboardCard.tsx index c31c2c390..721289684 100644 --- a/govtool/frontend/src/components/organisms/DashboardCards/ProposeGovActionDashboardCard.tsx +++ b/govtool/frontend/src/components/organisms/DashboardCards/ProposeGovActionDashboardCard.tsx @@ -37,7 +37,7 @@ export const ProposeGovActionDashboardCard = ({ navigate( isProposalDiscussionForumEnabled - ? PDF_PATHS.proposalDiscussion + ? PDF_PATHS.proposalDiscussionPropose : PATHS.createGovernanceAction, ); }, [deposit, votingPower, isProposalDiscussionForumEnabled]); diff --git a/govtool/frontend/src/consts/paths.ts b/govtool/frontend/src/consts/paths.ts index 972c002e5..296b61d7e 100644 --- a/govtool/frontend/src/consts/paths.ts +++ b/govtool/frontend/src/consts/paths.ts @@ -29,4 +29,5 @@ export const PATHS = { export const PDF_PATHS = { proposalDiscussion: "/proposal_discussion", proposalDiscussionProposal: "/proposal_discussion/:id", + proposalDiscussionPropose: "/proposal_discussion/propose", }; diff --git a/govtool/frontend/yarn.lock b/govtool/frontend/yarn.lock index 74b48eb9f..3f847890a 100644 --- a/govtool/frontend/yarn.lock +++ b/govtool/frontend/yarn.lock @@ -1581,10 +1581,10 @@ resolved "https://registry.npmjs.org/@intersect.mbo/intersectmbo.org-icons-set/-/intersectmbo.org-icons-set-1.0.8.tgz" integrity sha512-Y+5vYGlF3Smg/QscQT/4ZwsKTNm2C0GCs2czzYWrE4O4RV2YAAg9MZkQ52u8uZp3cEW0h9vr+f9W9ihhwsNHGQ== -"@intersect.mbo/pdf-ui@^0.2.7": - version "0.2.7" - resolved "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.2.7.tgz" - integrity sha512-vYmxs2F5Grk0Np/DfcytaXiPfgP8YWUYTKoWriS1DWSUdKZgj27DYQbPIL3dRjUW6kOC7rFDdbNQR9bZJ2YVkw== +"@intersect.mbo/pdf-ui@^0.2.8": + version "0.2.8" + resolved "https://registry.npmjs.org/@intersect.mbo/pdf-ui/-/pdf-ui-0.2.8.tgz" + integrity sha512-ioksMZ3G5PJ1RCZPJb5Ui6lKz6bgSk5R5HbjTCY1+AQIDjLIlYE0+gslwqxl1NDF6pLevJUGX+TZAXJgYUd6Vg== dependencies: "@fontsource/poppins" "^5.0.14" "@intersect.mbo/intersectmbo.org-icons-set" "^1.0.8" diff --git a/tests/govtool-frontend/playwright/lib/_mock/index.ts b/tests/govtool-frontend/playwright/lib/_mock/index.ts index b9c46e638..9fc38d672 100644 --- a/tests/govtool-frontend/playwright/lib/_mock/index.ts +++ b/tests/govtool-frontend/playwright/lib/_mock/index.ts @@ -30,6 +30,29 @@ export const invalid = { return " "; }, + username: () => { + const choice = faker.number.int({ min: 1, max: 6 }); + if (choice === 1) { + // Contains a space, which is invalid + return faker.lorem.word() + " " + faker.lorem.word(); + } else if (choice === 2) { + // Exceeds 30 characters, which is invalid + return faker.lorem.words(31).replace(/\s+/g, ""); + } else if (choice === 3) { + // Starts with a period, which is invalid + return "." + faker.internet.userName(); + } else if (choice === 4) { + // Starts with an underscore, which is invalid + return "_" + faker.internet.userName(); + } else if (choice === 5) { + // Contains an invalid character, such as a symbol + return faker.internet.userName() + "#"; + } else if (choice === 6) { + // Contains a hyphen + return faker.internet.userName() + "-"; + } + }, + email: () => { const choice = faker.number.int({ min: 1, max: 3 }); @@ -71,3 +94,29 @@ export const invalid = { return " "; }, }; + +export const valid = { + username: () => { + let username = faker.internet.userName().toLowerCase(); + + // Remove any invalid characters + username = username.replace(/[^a-z0-9._]/g, ""); + + // Ensure the username is between 1 and 30 characters + if (username.length > 30) { + username = username.substring(0, 30); + } + + // Ensure the first character is not a period or underscore + if (username.startsWith(".") || username.startsWith("_")) { + username = "a" + username.substring(1); + } + + // Ensure the username is not empty after the transformations + if (username.length === 0) { + username = "user" + faker.number.int({ min: 1, max: 9999 }); + } + + return username; + }, +}; diff --git a/tests/govtool-frontend/playwright/lib/_mock/infoProposedGAs.json b/tests/govtool-frontend/playwright/lib/_mock/infoProposedGAs.json new file mode 100644 index 000000000..f5fe2f80f --- /dev/null +++ b/tests/govtool-frontend/playwright/lib/_mock/infoProposedGAs.json @@ -0,0 +1,1110 @@ +{ + "data": [ + { + "id": 339, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "137", + "createdAt": "2024-07-01T10:19:22.617Z", + "updatedAt": "2024-07-01T10:19:22.617Z", + "user_govtool_username": "No name", + "content": { + "id": 338, + "attributes": { + "proposal_id": "339", + "prop_rev_active": true, + "prop_abstract": " ", + "prop_motivation": " ", + "prop_rationale": " ", + "gov_action_type_id": "1", + "prop_name": "First Draft", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-07-01T10:19:22.617Z", + "updatedAt": "2024-07-01T10:19:22.617Z", + "is_draft": false, + "user_id": "137", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 329, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "20", + "createdAt": "2024-07-01T06:18:34.760Z", + "updatedAt": "2024-07-01T06:18:34.760Z", + "user_govtool_username": "Anonymous", + "content": { + "id": 328, + "attributes": { + "proposal_id": "329", + "prop_rev_active": true, + "prop_abstract": " ", + "prop_motivation": " ", + "prop_rationale": " ", + "gov_action_type_id": "1", + "prop_name": "dQuad draft", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-07-01T06:18:34.760Z", + "updatedAt": "2024-07-01T06:18:34.760Z", + "is_draft": false, + "user_id": "20", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 323, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "20", + "createdAt": "2024-07-01T06:05:41.221Z", + "updatedAt": "2024-07-01T06:05:41.221Z", + "user_govtool_username": "Anonymous", + "content": { + "id": 322, + "attributes": { + "proposal_id": "323", + "prop_rev_active": true, + "prop_abstract": " ", + "prop_motivation": " ", + "prop_rationale": " ", + "gov_action_type_id": "1", + "prop_name": " ", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-07-01T06:05:41.235Z", + "updatedAt": "2024-07-01T06:05:41.235Z", + "is_draft": false, + "user_id": "20", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 319, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "127", + "createdAt": "2024-06-27T10:10:47.816Z", + "updatedAt": "2024-06-27T10:10:47.816Z", + "user_govtool_username": "Val", + "content": { + "id": 318, + "attributes": { + "proposal_id": "319", + "prop_rev_active": true, + "prop_abstract": "Summary", + "prop_motivation": "Motivation", + "prop_rationale": "Rationale", + "gov_action_type_id": "1", + "prop_name": "New proposal", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-27T10:10:47.838Z", + "updatedAt": "2024-06-27T10:10:47.838Z", + "is_draft": false, + "user_id": "127", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [ + { + "id": 62, + "prop_link": "https://docs.intersectmbo.org/intersect-community-grants/closed-grants/proposal-discussion-forum", + "prop_link_text": null + } + ], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 305, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 1, + "user_id": "127", + "createdAt": "2024-06-24T13:09:54.524Z", + "updatedAt": "2024-06-27T09:55:44.508Z", + "user_govtool_username": "Val", + "content": { + "id": 317, + "attributes": { + "proposal_id": "305", + "prop_rev_active": true, + "prop_abstract": "na", + "prop_motivation": "na", + "prop_rationale": "na", + "gov_action_type_id": "1", + "prop_name": "New Title", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-27T09:55:14.956Z", + "updatedAt": "2024-06-27T09:55:14.956Z", + "is_draft": false, + "user_id": "127", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 318, + "attributes": { + "prop_likes": 1, + "prop_dislikes": 0, + "prop_comments_number": 4, + "user_id": "137", + "createdAt": "2024-06-27T02:33:45.412Z", + "updatedAt": "2024-06-27T10:04:12.908Z", + "user_govtool_username": "No name", + "content": { + "id": 316, + "attributes": { + "proposal_id": "318", + "prop_rev_active": true, + "prop_abstract": " ", + "prop_motivation": " ", + "prop_rationale": " ", + "gov_action_type_id": "1", + "prop_name": " ", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-27T02:33:45.426Z", + "updatedAt": "2024-06-27T02:33:45.426Z", + "is_draft": false, + "user_id": "137", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 317, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 1, + "user_id": "124", + "createdAt": "2024-06-27T01:39:54.268Z", + "updatedAt": "2024-06-27T02:07:24.503Z", + "user_govtool_username": "Test", + "content": { + "id": 315, + "attributes": { + "proposal_id": "317", + "prop_rev_active": true, + "prop_abstract": " ", + "prop_motivation": " ", + "prop_rationale": " ", + "gov_action_type_id": "1", + "prop_name": " ", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-27T01:39:54.283Z", + "updatedAt": "2024-06-27T01:39:54.283Z", + "is_draft": false, + "user_id": "124", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 313, + "attributes": { + "prop_likes": 1, + "prop_dislikes": 0, + "prop_comments_number": 2, + "user_id": "19", + "createdAt": "2024-06-26T04:00:01.483Z", + "updatedAt": "2024-06-26T13:02:23.814Z", + "user_govtool_username": "pm00", + "content": { + "id": 309, + "attributes": { + "proposal_id": "313", + "prop_rev_active": true, + "prop_abstract": "test", + "prop_motivation": "test", + "prop_rationale": "test", + "gov_action_type_id": "1", + "prop_name": "test", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-26T04:00:01.497Z", + "updatedAt": "2024-06-26T04:00:01.497Z", + "is_draft": false, + "user_id": "19", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 312, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "19", + "createdAt": "2024-06-26T02:55:19.093Z", + "updatedAt": "2024-06-26T02:55:19.093Z", + "user_govtool_username": "pm00", + "content": { + "id": 308, + "attributes": { + "proposal_id": "312", + "prop_rev_active": true, + "prop_abstract": "test", + "prop_motivation": "test", + "prop_rationale": "test", + "gov_action_type_id": "1", + "prop_name": "test", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-26T02:55:19.113Z", + "updatedAt": "2024-06-26T02:55:19.113Z", + "is_draft": false, + "user_id": "19", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [ + { + "id": 56, + "prop_link": "https://test.com", + "prop_link_text": null + } + ], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 311, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "19", + "createdAt": "2024-06-26T01:35:26.674Z", + "updatedAt": "2024-06-26T01:35:26.674Z", + "user_govtool_username": "pm00", + "content": { + "id": 307, + "attributes": { + "proposal_id": "311", + "prop_rev_active": true, + "prop_abstract": "test", + "prop_motivation": "test", + "prop_rationale": "test", + "gov_action_type_id": "1", + "prop_name": "test", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-26T01:35:26.697Z", + "updatedAt": "2024-06-26T01:35:26.697Z", + "is_draft": false, + "user_id": "19", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [ + { + "id": 55, + "prop_link": "https://test.com", + "prop_link_text": null + } + ], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 310, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "19", + "createdAt": "2024-06-26T01:28:56.923Z", + "updatedAt": "2024-06-26T01:28:56.923Z", + "user_govtool_username": "pm00", + "content": { + "id": 306, + "attributes": { + "proposal_id": "310", + "prop_rev_active": true, + "prop_abstract": "test", + "prop_motivation": "test", + "prop_rationale": "test", + "gov_action_type_id": "1", + "prop_name": "test", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-26T01:28:56.947Z", + "updatedAt": "2024-06-26T01:28:56.947Z", + "is_draft": false, + "user_id": "19", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [ + { + "id": 54, + "prop_link": "https://test.com", + "prop_link_text": null + } + ], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 309, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "19", + "createdAt": "2024-06-25T22:55:52.976Z", + "updatedAt": "2024-06-25T22:55:52.976Z", + "user_govtool_username": "pm00", + "content": { + "id": 305, + "attributes": { + "proposal_id": "309", + "prop_rev_active": true, + "prop_abstract": "test", + "prop_motivation": "test", + "prop_rationale": "test", + "gov_action_type_id": "1", + "prop_name": "test", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-25T22:55:53.005Z", + "updatedAt": "2024-06-25T22:55:53.005Z", + "is_draft": false, + "user_id": "19", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [ + { + "id": 53, + "prop_link": "dfsd", + "prop_link_text": null + } + ], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 303, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "135", + "createdAt": "2024-06-24T10:20:19.799Z", + "updatedAt": "2024-06-24T10:20:19.799Z", + "user_govtool_username": "TestingUser", + "content": { + "id": 299, + "attributes": { + "proposal_id": "303", + "prop_rev_active": true, + "prop_abstract": "Test", + "prop_motivation": "Test", + "prop_rationale": "Test", + "gov_action_type_id": "1", + "prop_name": "Test", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-24T10:20:19.810Z", + "updatedAt": "2024-06-24T10:20:19.810Z", + "is_draft": false, + "user_id": "135", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 302, + "attributes": { + "prop_likes": 1, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "19", + "createdAt": "2024-06-20T15:50:40.146Z", + "updatedAt": "2024-06-20T18:29:28.590Z", + "user_govtool_username": "pm00", + "content": { + "id": 298, + "attributes": { + "proposal_id": "302", + "prop_rev_active": true, + "prop_abstract": "test", + "prop_motivation": "test", + "prop_rationale": "test", + "gov_action_type_id": "1", + "prop_name": "test", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-20T16:02:33.770Z", + "updatedAt": "2024-06-20T16:02:33.770Z", + "is_draft": false, + "user_id": "19", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [ + { + "id": 49, + "prop_link": "https://test.com/", + "prop_link_text": null + } + ], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 301, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 1, + "prop_comments_number": 13, + "user_id": "6", + "createdAt": "2024-06-20T14:10:41.553Z", + "updatedAt": "2024-06-20T15:39:13.447Z", + "user_govtool_username": "lorenzo.bruno@intersectmbo.org", + "content": { + "id": 296, + "attributes": { + "proposal_id": "301", + "prop_rev_active": true, + "prop_abstract": "ds", + "prop_motivation": "ds", + "prop_rationale": "ds", + "gov_action_type_id": "1", + "prop_name": "ds", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-20T14:10:41.564Z", + "updatedAt": "2024-06-20T14:10:41.564Z", + "is_draft": false, + "user_id": "6", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 299, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 5, + "user_id": "32", + "createdAt": "2024-06-20T10:47:43.456Z", + "updatedAt": "2024-06-20T13:46:49.580Z", + "user_govtool_username": "Michal", + "content": { + "id": 294, + "attributes": { + "proposal_id": "299", + "prop_rev_active": true, + "prop_abstract": "Test Abstract", + "prop_motivation": "Test Motivation", + "prop_rationale": "Test Rationale", + "gov_action_type_id": "1", + "prop_name": "Test", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-20T10:47:43.469Z", + "updatedAt": "2024-06-20T10:47:43.469Z", + "is_draft": false, + "user_id": "32", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 297, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "19", + "createdAt": "2024-06-19T15:57:47.949Z", + "updatedAt": "2024-06-19T15:57:47.949Z", + "user_govtool_username": "pm00", + "content": { + "id": 292, + "attributes": { + "proposal_id": "297", + "prop_rev_active": true, + "prop_abstract": "test", + "prop_motivation": "test", + "prop_rationale": "test", + "gov_action_type_id": "1", + "prop_name": "test", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-19T15:57:47.968Z", + "updatedAt": "2024-06-19T15:57:47.968Z", + "is_draft": false, + "user_id": "19", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [ + { + "id": 47, + "prop_link": "test.com", + "prop_link_text": null + } + ], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 331, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "124", + "createdAt": "2024-06-19T10:28:05.678Z", + "updatedAt": "2024-06-19T10:28:05.678Z", + "user_govtool_username": "Test", + "content": { + "id": 330, + "attributes": { + "proposal_id": "331", + "prop_rev_active": true, + "prop_abstract": " ", + "prop_motivation": " ", + "prop_rationale": " ", + "gov_action_type_id": "1", + "prop_name": " ", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-19T10:28:05.678Z", + "updatedAt": "2024-06-19T10:28:05.678Z", + "is_draft": false, + "user_id": "124", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 292, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 5, + "user_id": "124", + "createdAt": "2024-06-19T09:41:12.144Z", + "updatedAt": "2024-06-19T15:57:16.935Z", + "user_govtool_username": "Test", + "content": { + "id": 287, + "attributes": { + "proposal_id": "292", + "prop_rev_active": true, + "prop_abstract": "Fake abstract", + "prop_motivation": " Fake Motivation", + "prop_rationale": " Fake Rationale", + "gov_action_type_id": "1", + "prop_name": "fake title", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-19T10:13:32.814Z", + "updatedAt": "2024-06-19T10:13:32.814Z", + "is_draft": false, + "user_id": "124", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [ + { + "id": 45, + "prop_link": "google.com", + "prop_link_text": "Google" + } + ], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 291, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "129", + "createdAt": "2024-06-19T08:00:31.668Z", + "updatedAt": "2024-06-19T08:00:31.668Z", + "user_govtool_username": "Niraj3", + "content": { + "id": 285, + "attributes": { + "proposal_id": "291", + "prop_rev_active": true, + "prop_abstract": " ", + "prop_motivation": " ", + "prop_rationale": " ", + "gov_action_type_id": "1", + "prop_name": " ", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-19T08:00:31.668Z", + "updatedAt": "2024-06-19T08:00:31.668Z", + "is_draft": false, + "user_id": "129", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 286, + "attributes": { + "prop_likes": 1, + "prop_dislikes": 0, + "prop_comments_number": 2, + "user_id": "127", + "createdAt": "2024-06-18T14:50:58.504Z", + "updatedAt": "2024-06-19T12:30:16.464Z", + "user_govtool_username": "Val", + "content": { + "id": 280, + "attributes": { + "proposal_id": "286", + "prop_rev_active": true, + "prop_abstract": "na", + "prop_motivation": "na", + "prop_rationale": "na", + "gov_action_type_id": "1", + "prop_name": "Test 4", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-18T14:50:58.516Z", + "updatedAt": "2024-06-18T14:50:58.516Z", + "is_draft": false, + "user_id": "127", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 333, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "126", + "createdAt": "2024-06-18T08:18:26.508Z", + "updatedAt": "2024-06-18T08:18:26.508Z", + "user_govtool_username": "Kneerose", + "content": { + "id": 332, + "attributes": { + "proposal_id": "333", + "prop_rev_active": true, + "prop_abstract": " ", + "prop_motivation": " ", + "prop_rationale": " ", + "gov_action_type_id": "1", + "prop_name": " test", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-18T08:18:26.508Z", + "updatedAt": "2024-06-18T08:18:26.508Z", + "is_draft": false, + "user_id": "126", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 288, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 1, + "user_id": "126", + "createdAt": "2024-06-18T08:18:26.508Z", + "updatedAt": "2024-06-19T04:42:25.687Z", + "user_govtool_username": "Kneerose", + "content": { + "id": 282, + "attributes": { + "proposal_id": "288", + "prop_rev_active": true, + "prop_abstract": " ", + "prop_motivation": " ", + "prop_rationale": " ", + "gov_action_type_id": "1", + "prop_name": " ", + "prop_receiving_address": null, + "prop_amount": null, + "createdAt": "2024-06-18T08:18:26.508Z", + "updatedAt": "2024-06-18T08:18:26.508Z", + "is_draft": false, + "user_id": "126", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 280, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 1, + "prop_comments_number": 4, + "user_id": "121", + "createdAt": "2024-06-17T08:30:36.868Z", + "updatedAt": "2024-06-18T09:26:15.103Z", + "user_govtool_username": "Brock.Kilback", + "content": { + "id": 274, + "attributes": { + "proposal_id": "280", + "prop_rev_active": true, + "prop_abstract": "Conicio cubo amet. Vorago totidem quod in patior explicabo delicate.", + "prop_motivation": "Vel tot audio cilicium uredo. Occaecati crepusculum cuppedia deporto valeo illum.", + "prop_rationale": "Vulgo quod denuo admitto. Aspicio tersus uredo depromo caelum apud pectus vitae commemoro.", + "gov_action_type_id": "1", + "prop_name": "Baumbach, Hauck and Bartell", + "prop_receiving_address": "addr_test1qqqqqqqqqqa4kpmh", + "prop_amount": 520, + "createdAt": "2024-06-17T08:30:36.893Z", + "updatedAt": "2024-06-17T08:30:36.893Z", + "is_draft": false, + "user_id": "121", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + }, + { + "id": 277, + "attributes": { + "prop_likes": 0, + "prop_dislikes": 0, + "prop_comments_number": 0, + "user_id": "121", + "createdAt": "2024-06-17T08:27:52.316Z", + "updatedAt": "2024-06-17T08:27:52.316Z", + "user_govtool_username": "Brock.Kilback", + "content": { + "id": 271, + "attributes": { + "proposal_id": "277", + "prop_rev_active": true, + "prop_abstract": "Terror commodi terebro arma torrens caterva vivo alias decumbo. Ubi volup aufero adficio audax.", + "prop_motivation": "Terror thermae delibero cinis crux somniculosus. Suscipit conspergo administratio tutamen cursim combibo.", + "prop_rationale": "Conculco ater amor beneficium cunabula qui vespillo tempora textilis allatus. Admiratio cuppedia repudiandae voluptatem anser calculus attonbitus.", + "gov_action_type_id": "1", + "prop_name": "Orn - Crist", + "prop_receiving_address": "addr_test1qqqqqqqqqqa4kpmh", + "prop_amount": 591, + "createdAt": "2024-06-17T08:27:52.329Z", + "updatedAt": "2024-06-17T08:27:52.329Z", + "is_draft": false, + "user_id": "121", + "prop_submitted": false, + "prop_submission_tx_hash": null, + "prop_submission_date": null, + "proposal_links": [], + "gov_action_type": { + "id": 1, + "attributes": { + "gov_action_type_name": "Info", + "createdAt": "2024-05-27T15:06:15.640Z", + "updatedAt": "2024-05-27T15:06:15.640Z" + } + } + } + } + } + } + ], + "meta": { + "pagination": { + "page": 1, + "pageSize": 25, + "pageCount": 8, + "total": 194 + } + } +} diff --git a/tests/govtool-frontend/playwright/lib/_mock/mockAttachment.png b/tests/govtool-frontend/playwright/lib/_mock/mockAttachment.png new file mode 100644 index 000000000..6f8fb43b7 Binary files /dev/null and b/tests/govtool-frontend/playwright/lib/_mock/mockAttachment.png differ diff --git a/tests/govtool-frontend/playwright/lib/constants/docsUrl.ts b/tests/govtool-frontend/playwright/lib/constants/docsUrl.ts index 3f6c27f0d..faab5c95f 100644 --- a/tests/govtool-frontend/playwright/lib/constants/docsUrl.ts +++ b/tests/govtool-frontend/playwright/lib/constants/docsUrl.ts @@ -9,3 +9,6 @@ export const ABSTAIN_VOTE_DOC_URL = `${environments.docsUrl}/how-to-use-the-govt export const SIGNAL_NO_CONFIDENCE_VOTE_DOC_URL = `${environments.docsUrl}/how-to-use-the-govtool/using-govtool/delegating/signal-no-confidence-on-every-vote`; export const FAQS_DOC_URL = `${environments.docsUrl}/faqs`; export const GUIDES_DOC_URL = `${environments.docsUrl}/about/what-is-sanchonet-govtool`; +export const PRIVACY_POLICY = `${environments.docsUrl}/legal/privacy-policy`; +export const TERMS_AND_CONDITIONS = `${environments.docsUrl}/legal/terms-and-conditions`; +export const HELP_DOC_URL = `${environments.docsUrl}/support/get-help-in-discord`; diff --git a/tests/govtool-frontend/playwright/lib/constants/staticWallets.ts b/tests/govtool-frontend/playwright/lib/constants/staticWallets.ts index 38e6dfa8a..b0555112c 100644 --- a/tests/govtool-frontend/playwright/lib/constants/staticWallets.ts +++ b/tests/govtool-frontend/playwright/lib/constants/staticWallets.ts @@ -18,6 +18,7 @@ export const user01Wallet: StaticWallet = staticWallets[5]; // Username is already set export const proposal01Wallet: StaticWallet = staticWallets[10]; +export const proposal02Wallet: StaticWallet = staticWallets[11]; export const adaHolderWallets = [ adaHolder01Wallet, diff --git a/tests/govtool-frontend/playwright/lib/fixtures/proposal.ts b/tests/govtool-frontend/playwright/lib/fixtures/proposal.ts index 686629f9a..1ac776878 100644 --- a/tests/govtool-frontend/playwright/lib/fixtures/proposal.ts +++ b/tests/govtool-frontend/playwright/lib/fixtures/proposal.ts @@ -2,7 +2,7 @@ import { proposal01Wallet } from "@constants/staticWallets"; import { test as base } from "@fixtures/walletExtension"; import { createNewPageWithWallet } from "@helpers/page"; import ProposalDiscussionDetailsPage from "@pages/proposalDiscussionDetailsPage"; -import ProposalDiscussionPage from "@pages/proposalDiscussionPage"; +import ProposalSubmissionPage from "@pages/proposalSubmissionPage"; type TestOptions = { proposalId: number; @@ -12,16 +12,18 @@ type TestOptions = { export const test = base.extend({ pollEnabled: [false, { option: true }], - proposalId: async ({ page, browser, pollEnabled }, use) => { + proposalId: async ({ browser, pollEnabled }, use) => { // setup const proposalPage = await createNewPageWithWallet(browser, { storageState: ".auth/proposal01.json", wallet: proposal01Wallet, }); - const proposalDiscussionPage = new ProposalDiscussionPage(proposalPage); - await proposalDiscussionPage.goto(); - const proposalId = await proposalDiscussionPage.createProposal(); + const proposalCreationPage = new ProposalSubmissionPage(proposalPage); + await proposalCreationPage.goto(); + + const proposalId = await proposalCreationPage.createProposal(); + const proposalDetailsPage = new ProposalDiscussionDetailsPage(proposalPage); if (pollEnabled) { @@ -31,7 +33,6 @@ export const test = base.extend({ await use(proposalId); // cleanup - await proposalDetailsPage.goto(proposalId); await proposalDetailsPage.deleteProposal(); }, }); diff --git a/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionDetailsPage.ts b/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionDetailsPage.ts index cedee9c55..36a878e52 100644 --- a/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionDetailsPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionDetailsPage.ts @@ -10,10 +10,7 @@ export default class ProposalDiscussionDetailsPage { readonly dislikeBtn = this.page.getByRole("button", { name: "proposal dislikes", }); - readonly commentBtn = this.page.getByRole("button", { - name: "Comment", - exact: true, - }); // this.page.getByTestId("comment-button"); + readonly commentBtn = this.page.getByTestId("comment-button"); readonly addPollBtn = this.page.getByRole("button", { name: "Add Poll" }); // BUG missing test id readonly SubmitBtn = this.page.getByTestId("submit-button"); readonly menuBtn = this.page.getByTestId("menu-button"); @@ -30,17 +27,19 @@ export default class ProposalDiscussionDetailsPage { readonly pollYesBtn = this.page.getByRole("button", { name: "Yes" }); //BUG missing test id readonly pollNoBtn = this.page.getByRole("button", { name: "No" }); //BUG missing test id readonly showReplyBtn = this.page.getByTestId("show-more-reply"); - readonly closePollYesBtn = this.page.getByRole("button", { - name: "Yes, close Poll", - }); // BUG missing test id + readonly closePollYesBtn = this.page.getByTestId("close-the-poll-button"); readonly changeVoteBtn = this.page.getByRole("button", { name: "Change Vote", }); + readonly verifyIdentityBtn = this.page.getByRole("button", { + name: "Verify your identity", + }); + readonly submitAsGABtn = this.page.getByTestId("submit-as-GA-button"); // Indicators readonly likesCounts = this.page.getByTestId("likes-count"); readonly dislikesCounts = this.page.getByTestId("dislikse-count"); - readonly commentsCount = this.page.getByTestId("comments-count"); + readonly commentCount = this.page.getByTestId("comment-count"); // Cards readonly pollVoteCard = this.page.getByTestId("poll-vote-card"); @@ -55,7 +54,7 @@ export default class ProposalDiscussionDetailsPage { async goto(proposalId: number) { await this.page.goto( - `${environments.frontendUrl}/connected/proposal_pillar/proposal_discussion/${proposalId}` + `${environments.frontendUrl}/proposal_discussion/${proposalId}` ); } @@ -69,15 +68,13 @@ export default class ProposalDiscussionDetailsPage { async addComment(comment: string) { await this.commentInput.fill(comment); - await this.page - .getByRole("button", { name: "Comment", exact: true }) - .click(); + await this.page.getByTestId("comment-button").click(); } async replyComment(reply: string) { await this.page.getByRole("button", { name: "Reply" }).click(); await this.page.getByPlaceholder("Add comment").fill(reply); - await this.page.getByRole("button", { name: "Comment" }).nth(2).click(); + await this.page.getByTestId("reply-comment-button").click(); } async sortAndValidate( @@ -111,11 +108,7 @@ export default class ProposalDiscussionDetailsPage { await this.page.waitForTimeout(2_000); await this.page.locator("#menu-button").click(); - await this.page.getByRole("menuitem", { name: "Delete Proposal" }).click(); - - // confirm deletion - await this.page - .getByRole("button", { name: "Yes, delete my proposal" }) - .click(); + await this.page.getByTestId("delete-proposal").click(); + await this.page.getByTestId("delete-proposal-yes-button").click(); } } diff --git a/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionPage.ts b/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionPage.ts index cd7096e58..ff5e45d4a 100644 --- a/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/proposalDiscussionPage.ts @@ -1,10 +1,10 @@ import { faker } from "@faker-js/faker"; import { generateWalletAddress } from "@helpers/cardano"; import { extractProposalIdFromUrl } from "@helpers/string"; -import { Page } from "@playwright/test"; +import { expect, Locator, Page } from "@playwright/test"; +import { ProposalCreateRequest, ProposedGovAction } from "@types"; import environments from "lib/constants/environments"; import ProposalDiscussionDetailsPage from "./proposalDiscussionDetailsPage"; -import {ProposalCreateRequest} from "@types"; export default class ProposalDiscussionPage { // Buttons @@ -27,13 +27,12 @@ export default class ProposalDiscussionPage { readonly verifyIdentityBtn = this.page.getByRole("button", { name: "Verify your identity", }); + readonly addLinkBtn = this.page.getByRole("button", { name: "Add link" }); constructor(private readonly page: Page) {} async goto() { - await this.page.goto( - `${environments.frontendUrl}/connected/proposal_pillar/proposal_discussion` - ); + await this.page.goto(`${environments.frontendUrl}/proposal_discussion`); await this.page.waitForTimeout(2_000); } @@ -47,15 +46,31 @@ export default class ProposalDiscussionPage { async viewFirstProposal(): Promise { await this.page - .locator('[data-testid^="govaction-"][data-testid$="-view-detail"]') + .locator('[data-testid^="proposal-"][data-testid$="-view-details"]') .first() .click(); return new ProposalDiscussionDetailsPage(this.page); } async getAllProposals() { - await this.page.waitForTimeout(2_000); - return this.page.locator('[data-testid$="-card"]').all(); // BUG + await this.page.waitForTimeout(4_000); // waits for proposals to render + // BUG Select all elements with data-testid attribute + const elements = await this.page.$$("[data-testid]"); + + // Regex pattern to match IDs starting with "proposal" and ending with numbers + const pattern = /^proposal-\d+$/; + + // Extract the data-testid attributes + const proposalCards: Locator[] = []; + for (const element of elements) { + const dataTestId = await element.getAttribute("data-testid"); + if (pattern.test(dataTestId)) { + proposalCards.push(this.page.getByTestId(dataTestId)); + } + } + + return proposalCards; + // BUG return this.page.locator('[data-testid$="-card"]').all(); } async setUsername(name: string) { @@ -88,11 +103,11 @@ export default class ProposalDiscussionPage { prop_amount: faker.number.int({ min: 100, max: 1000 }).toString(), is_draft: false, }; - await this.proposalCreateBtn.click(); await this.continueBtn.click(); await this.fillForm(proposalRequest); + await this.continueBtn.click(); await this.page.getByRole("button", { name: "Submit" }).click(); @@ -110,10 +125,72 @@ export default class ProposalDiscussionPage { await this.page.getByPlaceholder("Summary...").fill(data.prop_abstract); await this.page.getByLabel("Motivation *").fill(data.prop_motivation); await this.page.getByLabel("Rationale *").fill(data.prop_rationale); - await this.page - .getByLabel("Receiving address *") - .fill(data.prop_receiving_address); - await this.page.getByPlaceholder("e.g.").fill(data.prop_amount); + for (const link of data.proposal_links) { + await this.addLinkBtn.click(); + + await this.page + .getByPlaceholder("https://website.com") + .fill(link.prop_link); + await this.page.getByPlaceholder("Text").fill(link.prop_link_text); + } + } + + async filterProposalByNames(names: string[]) { + for (const name of names) { + await this.page.getByLabel(name).click(); + } + } + + async unFilterProposalByNames(names: string[]) { + for (const name of names) { + await this.page.getByLabel(name).click(); + } + } + + async validateFilters(filters: string[]) { + const proposalCards = await this.getAllProposals(); + + for (const proposalCard of proposalCards) { + const hasFilter = await this._validateFiltersInProposalCard( + proposalCard, + filters + ); + expect(hasFilter).toBe(true); + } + } + + async sortAndValidate( + option: "asc" | "desc", + validationFn: (p1: ProposedGovAction, p2: ProposedGovAction) => boolean + ) { + const responsePromise = this.page.waitForResponse((response) => + response + .url() + .includes(`&sort[createdAt]=${option}&populate[0]=proposal_links`) + ); + + await this.sortBtn.click(); + const response = await responsePromise; + + let proposals: ProposedGovAction[] = (await response.json()).data; + + // API validation + for (let i = 0; i <= proposals.length - 2; i++) { + const isValid = validationFn(proposals[i], proposals[i + 1]); + expect(isValid).toBe(true); + } + } + + async _validateFiltersInProposalCard( + proposalCard: Locator, + filters: string[] + ): Promise { + const proposalTypeTextContent = await proposalCard + .locator('[data-testid$="-type"]') + .textContent(); + const govActionType = proposalTypeTextContent.split(":")[1]; + + return filters.includes(govActionType); } } diff --git a/tests/govtool-frontend/playwright/lib/pages/proposalSubmissionPage.ts b/tests/govtool-frontend/playwright/lib/pages/proposalSubmissionPage.ts index 9496b587b..ed318b068 100644 --- a/tests/govtool-frontend/playwright/lib/pages/proposalSubmissionPage.ts +++ b/tests/govtool-frontend/playwright/lib/pages/proposalSubmissionPage.ts @@ -1,12 +1,14 @@ +import environments from "@constants/environments"; import { faker } from "@faker-js/faker"; +import { ShelleyWallet } from "@helpers/crypto"; import { expectWithInfo } from "@helpers/exceptionHandler"; -import { Logger } from "@helpers/logger"; import { downloadMetadata } from "@helpers/metadata"; +import { extractProposalIdFromUrl } from "@helpers/string"; import { invalid } from "@mock/index"; import { Download, Page, expect } from "@playwright/test"; import metadataBucketService from "@services/metadataBucketService"; -import { IProposalForm, ProposalType } from "@types"; -import environments from "lib/constants/environments"; +import { ProposalCreateRequest, ProposalLink, ProposalType } from "@types"; + const formErrors = { proposalTitle: ["max-80-characters-error", "this-field-is-required-error"], abstract: "this-field-is-required-error", @@ -19,61 +21,71 @@ const formErrors = { export default class ProposalSubmissionPage { // modals - readonly registrationSuccessModal = this.page.getByTestId( - "governance-action-submitted-modal" - ); + readonly registrationSuccessModal = + this.page.getByTestId("ga-submitted-modal"); readonly registrationErrorModal = this.page.getByTestId( "create-governance-action-error-modal" ); // buttons + readonly proposalCreateBtn = this.page.getByRole("button", { + name: "Propose a Governance Action", + }); readonly registerBtn = this.page.getByTestId("register-button"); readonly skipBtn = this.page.getByTestId("skip-button"); readonly confirmBtn = this.page.getByTestId("confirm-modal-button"); - readonly continueBtn = this.page.getByTestId("continue-button"); - readonly addLinkBtn = this.page.getByRole("button", { name: "+ Add link" }); // BUG testid= add-link-button - readonly infoRadioButton = this.page.getByTestId("Info-radio"); - readonly treasuryRadioButton = this.page.getByTestId("Treasury-radio"); + readonly continueBtn = this.page.getByRole("button", { name: "Continue" }); //BUG testid = continue-button + readonly addLinkBtn = this.page.getByRole("button", { name: "Add link" }); // BUG testid= add-link-button + readonly infoBtn = this.page.getByRole("option", { name: "Info" }); // BUG missing test id + readonly treasuryBtn = this.page.getByRole("option", { name: "Treasury" }); // BUG missing test id readonly editSubmissionButton = this.page.getByTestId( "edit-submission-button" ); + readonly verifyIdentityBtn = this.page.getByRole("button", { + name: "Verify your identity", + }); + readonly governanceActionType = this.page.getByLabel( + "Governance Action Type *" + ); // BUG missing test id + readonly saveDraftBtn = this.page.getByTestId("save-draft-button"); + readonly submitBtn = this.page.getByRole("button", { name: "Submit" }); // BUG missing test id + readonly createNewProposalBtn = this.page.getByRole("button", { + name: "Create new Proposal", + }); // input fields - readonly titleInput = this.page.getByPlaceholder("A name for this Action"); // BUG testid = title-input - readonly abstractInput = this.page.getByPlaceholder("Summary"); // BUG testid = abstract-input - readonly metadataUrlInput = this.page.getByTestId("metadata-url-input"); - readonly motivationInput = this.page.getByPlaceholder( - "Problem this GA will solve" - ); // BUG testid = motivation-input - readonly rationaleInput = this.page.getByPlaceholder( - "Content of Governance Action" - ); // BUG testid = rationale-input - readonly linkInput = this.page.getByPlaceholder("https://website.com/"); // BUG testid = link-input - readonly receivingAddressInput = this.page.getByPlaceholder( - "The address to receive funds" - ); - readonly amountInput = this.page.getByPlaceholder("e.g."); + readonly titleInput = this.page.getByLabel("Title *"); // BUG testid = title-input + readonly abstractInput = this.page.getByLabel("Abstract *"); // BUG testid = abstract-input + readonly metadataUrlInput = this.page.getByPlaceholder("URL"); // BUG missing test id + readonly motivationInput = this.page.getByLabel("Motivation *"); // BUG testid = motivation-input + readonly rationaleInput = this.page.getByLabel("Rationale *"); // BUG testid = rationale-input + readonly linkInput = this.page.getByLabel("Link #1 URL"); // BUG testid = link-input + readonly linkText = this.page.getByLabel("Link #1 Text"); // BUG missing testid + readonly receivingAddressInput = this.page.getByLabel("Receiving address *"); // BUG missing testid + readonly amountInput = this.page.getByTestId("amount-input"); + readonly closeDraftSuccessModalBtn = this.page.getByTestId( + "delete-proposal-yes-button" + ); //BUG Improper test ids constructor(private readonly page: Page) {} async goto() { - await this.page.goto( - `${environments.frontendUrl}/create_governance_action` - ); - await this.continueBtn.click(); - } + await this.page.goto(`${environments.frontendUrl}/proposal_discussion`); - async register(governanceProposal: IProposalForm) { - await this.fillupForm(governanceProposal); + await this.page.waitForTimeout(2_000); // wait until page load properly + + await this.verifyIdentityBtn.click(); + await this.proposalCreateBtn.click(); await this.continueBtn.click(); - await this.continueBtn.click(); - await this.page.getByRole("checkbox").click(); - await this.continueBtn.click(); + } + async fillUpValidMetadata() { this.page - .getByRole("button", { name: `${governanceProposal.type}.jsonld` }) + .getByRole("button", { + name: "data.jsonld", + }) .click(); // BUG test id = metadata-download-button const dRepMetadata = await this.downloadVoteMetadata(); @@ -82,7 +94,7 @@ export default class ProposalSubmissionPage { dRepMetadata.data ); await this.metadataUrlInput.fill(url); - await this.continueBtn.click(); + await this.submitBtn.click(); } async downloadVoteMetadata() { @@ -90,55 +102,95 @@ export default class ProposalSubmissionPage { return downloadMetadata(download); } - async fillupForm(governanceProposal: IProposalForm) { - await this.titleInput.fill(governanceProposal.title); - await this.abstractInput.fill(governanceProposal.abstract); - await this.motivationInput.fill(governanceProposal.motivation); - await this.rationaleInput.fill(governanceProposal.rationale); + async fillupFormWithTypeSelected(governanceProposal: ProposalCreateRequest) { + await this.fillCommonFields(governanceProposal); - if (governanceProposal.type === "Treasury") { - await this.receivingAddressInput.fill( - governanceProposal.receivingAddress - ); - await this.amountInput.fill(governanceProposal.amount); + if (governanceProposal.gov_action_type_id === 1) { + await this.fillTreasuryFields(governanceProposal); + } + + if (governanceProposal.proposal_links != null) { + await this.fillProposalLinks(governanceProposal.proposal_links); + } + } + + async fillupForm(governanceProposal: ProposalCreateRequest) { + await this.governanceActionType.click(); + + if (governanceProposal.gov_action_type_id === 0) { + await this.infoBtn.click(); + } else { + await this.treasuryBtn.click(); } + await this.fillupFormWithTypeSelected(governanceProposal); + } + + async fillCommonFields(governanceProposal: ProposalCreateRequest) { + await this.titleInput.fill(governanceProposal.prop_name); + await this.abstractInput.fill(governanceProposal.prop_abstract); + await this.motivationInput.fill(governanceProposal.prop_motivation); + await this.rationaleInput.fill(governanceProposal.prop_rationale); + } - if (governanceProposal.extraContentLinks != null) { - for (let i = 0; i < governanceProposal.extraContentLinks.length; i++) { - if (i > 0) { - this.page - .getByRole("button", { - name: "+ Add link", - }) - .click(); // BUG - } - await this.linkInput - .nth(i) - .fill(governanceProposal.extraContentLinks[i]); + async fillTreasuryFields(governanceProposal: ProposalCreateRequest) { + await this.receivingAddressInput.fill( + governanceProposal.prop_receiving_address + ); + await this.amountInput.fill(governanceProposal.prop_amount); + } + + async fillProposalLinks(proposal_links: Array) { + for (let i = 0; i < proposal_links.length; i++) { + if (i > 0) { + await this.addLinkBtn.click(); } + await this.linkInput.fill(proposal_links[i].prop_link); + await this.linkText.fill(proposal_links[i].prop_link_text); } } - async validateForm(governanceProposal: IProposalForm) { - await this.fillupForm(governanceProposal); + async getAllDrafts() { + await this.page.waitForTimeout(2_000); // wait until draft is loaded + return await this.page + .locator('[data-testid^="draft-"][data-testid$="-card"]') + .all(); + } + + async getFirstDraft() { + await this.page.waitForTimeout(2_000); // wait until draft is loaded + return this.page + .locator('[data-testid^="draft-"][data-testid$="-card"]') + .first(); + } + + async viewFirstDraft() { + await this.page.waitForTimeout(2_000); // wait until draft is loaded + return await this.page + .locator('[data-testid^="draft-"][data-testid$="-start-editing"]') + .first() + .click(); + } + + async validateForm(governanceProposal: ProposalCreateRequest) { + await this.fillupFormWithTypeSelected(governanceProposal); for (const err of formErrors.proposalTitle) { await expect(this.page.getByTestId(err)).toBeHidden(); } expect(await this.abstractInput.textContent()).toEqual( - governanceProposal.abstract + governanceProposal.prop_abstract ); expect(await this.rationaleInput.textContent()).toEqual( - governanceProposal.rationale + governanceProposal.prop_rationale ); expect(await this.motivationInput.textContent()).toEqual( - governanceProposal.motivation + governanceProposal.prop_motivation ); - if (governanceProposal.type === "Treasury") { + if (governanceProposal.gov_action_type_id === 1) { await expect( this.page.getByTestId(formErrors.receivingAddress) ).toBeHidden(); @@ -153,8 +205,8 @@ export default class ProposalSubmissionPage { await expect(this.continueBtn).toBeEnabled(); } - async inValidateForm(governanceProposal: IProposalForm) { - await this.fillupForm(governanceProposal); + async inValidateForm(governanceProposal: ProposalCreateRequest) { + await this.fillupFormWithTypeSelected(governanceProposal); function convertTestIdToText(testId: string) { let text = testId.replace("-error", ""); @@ -183,9 +235,10 @@ export default class ProposalSubmissionPage { expectWithInfo( async () => expect(proposalTitleErrors.length).toEqual(1), - `valid title: ${governanceProposal.title}` + `valid title: ${governanceProposal.prop_name}` ); - if (governanceProposal.type === "Treasury") { + + if (governanceProposal.gov_action_type_id === 1) { const receiverAddressErrors = await getErrorsByPattern( this.page, new RegExp(convertTestIdToText(formErrors.receivingAddress)) @@ -193,7 +246,7 @@ export default class ProposalSubmissionPage { expectWithInfo( async () => expect(receiverAddressErrors.length).toEqual(1), - `valid address: ${governanceProposal.receivingAddress}` + `valid address: ${governanceProposal.prop_receiving_address}` ); const amountPattern = generateRegexPattern(formErrors.amount); @@ -201,38 +254,38 @@ export default class ProposalSubmissionPage { expectWithInfo( async () => expect(amountErrors.length).toEqual(1), - `valid amount: ${governanceProposal.amount}` + `valid amount: ${governanceProposal.prop_amount}` ); } expectWithInfo( async () => expect(await this.abstractInput.textContent()).not.toEqual( - governanceProposal.abstract + governanceProposal.prop_abstract ), - `valid abstract: ${governanceProposal.abstract}` + `valid abstract: ${governanceProposal.prop_abstract}` ); expectWithInfo( async () => expect(await this.abstractInput.textContent()).not.toEqual( - governanceProposal.motivation + governanceProposal.prop_motivation ), - `valid motivation: ${governanceProposal.motivation}` + `valid motivation: ${governanceProposal.prop_motivation}` ); expectWithInfo( async () => expect(await this.abstractInput.textContent()).not.toEqual( - governanceProposal.rationale + governanceProposal.prop_rationale ), - `valid rationale: ${governanceProposal.rationale}` + `valid rationale: ${governanceProposal.prop_rationale}` ); expectWithInfo( async () => await expect(this.page.getByTestId(formErrors.link)).toBeVisible(), - `valid link: ${governanceProposal.extraContentLinks[0]}` + `valid link: ${governanceProposal.proposal_links[0].prop_link}` ); await expect(this.continueBtn).toBeDisabled(); @@ -240,20 +293,28 @@ export default class ProposalSubmissionPage { generateValidProposalFormFields( proposalType: ProposalType, + is_draft?: boolean, receivingAddress?: string ) { - const proposal: IProposalForm = { - title: faker.lorem.sentence(6), - abstract: faker.lorem.paragraph(2), - motivation: faker.lorem.paragraphs(2), - rationale: faker.lorem.paragraphs(2), - - extraContentLinks: [faker.internet.url()], - type: proposalType, + const proposal: ProposalCreateRequest = { + prop_name: faker.lorem.sentence(6), + prop_abstract: faker.lorem.words(5), + prop_motivation: faker.lorem.words(5), + prop_rationale: faker.lorem.words(5), + + proposal_links: [ + { + prop_link: faker.internet.url(), + prop_link_text: faker.internet.domainWord(), + }, + ], + gov_action_type_id: proposalType === ProposalType.info ? 0 : 1, + is_draft: !!is_draft, }; + if (proposalType === ProposalType.treasury) { - (proposal.receivingAddress = receivingAddress), - (proposal.amount = faker.number + (proposal.prop_receiving_address = receivingAddress), + (proposal.prop_amount = faker.number .int({ min: 100, max: 1000 }) .toString()); } @@ -261,19 +322,49 @@ export default class ProposalSubmissionPage { } generateInValidProposalFormFields(proposalType: ProposalType) { - const proposal: IProposalForm = { - title: invalid.proposalTitle(), - abstract: invalid.paragraph(), - motivation: invalid.paragraph(), - rationale: invalid.paragraph(), - - extraContentLinks: [invalid.url()], - type: proposalType, + const proposal: ProposalCreateRequest = { + prop_name: invalid.proposalTitle(), + prop_abstract: invalid.paragraph(), + prop_motivation: invalid.paragraph(), + prop_rationale: invalid.paragraph(), + + proposal_links: [ + { + prop_link: invalid.url(), + prop_link_text: invalid.name(), + }, + ], + gov_action_type_id: proposalType === ProposalType.info ? 0 : 1, + is_draft: false, }; + if (proposalType === ProposalType.treasury) { - (proposal.receivingAddress = faker.location.streetAddress()), - (proposal.amount = invalid.amount()); + (proposal.prop_receiving_address = faker.location.streetAddress()), + (proposal.prop_amount = invalid.amount()); } return proposal; } + + async createProposal(): Promise { + await this.addLinkBtn.click(); + const receivingAddr = (await ShelleyWallet.generate()).rewardAddressBech32( + 0 + ); + + const proposalRequest: ProposalCreateRequest = + this.generateValidProposalFormFields( + ProposalType.treasury, + false, + receivingAddr + ); + await this.fillupForm(proposalRequest); + await this.continueBtn.click(); + await this.submitBtn.click(); + + // Wait for redirection to `proposal-discussion-details` page + await this.page.waitForTimeout(2_000); + + const currentPageUrl = this.page.url(); + return extractProposalIdFromUrl(currentPageUrl); + } } diff --git a/tests/govtool-frontend/playwright/lib/types.ts b/tests/govtool-frontend/playwright/lib/types.ts index e323931b5..1b0cf3dfc 100644 --- a/tests/govtool-frontend/playwright/lib/types.ts +++ b/tests/govtool-frontend/playwright/lib/types.ts @@ -52,17 +52,6 @@ export type IDRepInfo = { extraContentLinks?: string[]; }; -export type IProposalForm = { - title: string; - abstract: string; - motivation: string; - rationale: string; - extraContentLinks?: string[]; - type: ProposalType; - receivingAddress?: string; - amount?: string; -}; - export enum ProposalType { info = "Info", treasury = "Treasury", @@ -123,7 +112,6 @@ export type CommentResponse = { }; }; - export type ProposalLink = { prop_link: string; prop_link_text: string; @@ -139,4 +127,13 @@ export type ProposalCreateRequest = { prop_receiving_address?: string; prop_amount?: string; is_draft: boolean; -}; \ No newline at end of file +}; + +export type ProposedGovAction = { + id: number; + attributes: { + gov_action_type_name: string; + createdAt: string; + updatedAt: string; + }; +}; diff --git a/tests/govtool-frontend/playwright/package-lock.json b/tests/govtool-frontend/playwright/package-lock.json index 5771210af..bace61f75 100644 --- a/tests/govtool-frontend/playwright/package-lock.json +++ b/tests/govtool-frontend/playwright/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@cardanoapi/cardano-test-wallet": "^2.0.0", + "@cardanoapi/cardano-test-wallet": "^2.0.1", "@faker-js/faker": "^8.4.1", "@noble/curves": "^1.3.0", "@noble/ed25519": "^2.0.0", @@ -87,9 +87,9 @@ } }, "node_modules/@cardanoapi/cardano-test-wallet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cardanoapi/cardano-test-wallet/-/cardano-test-wallet-2.0.0.tgz", - "integrity": "sha512-/8n83MzYgZnPv6ODYBGGwgnl9FPT1DU9BXfXeIicJQNhtWbL+QQWVa3cAvTiY3so3BfH5IaLjSnkaQRP4tBiSA==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@cardanoapi/cardano-test-wallet/-/cardano-test-wallet-2.0.1.tgz", + "integrity": "sha512-WpvFIOYh2d0HTi8ye+b62YtCOQTqsIwLqLabcDt4yoQJWMD5SiDDypd5TA1dU17Y0uAJ/oz4GIupch/PWsur2A==" }, "node_modules/@cbor-extract/cbor-extract-linux-x64": { "version": "2.2.0", @@ -3347,9 +3347,9 @@ "dev": true }, "@cardanoapi/cardano-test-wallet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cardanoapi/cardano-test-wallet/-/cardano-test-wallet-2.0.0.tgz", - "integrity": "sha512-/8n83MzYgZnPv6ODYBGGwgnl9FPT1DU9BXfXeIicJQNhtWbL+QQWVa3cAvTiY3so3BfH5IaLjSnkaQRP4tBiSA==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@cardanoapi/cardano-test-wallet/-/cardano-test-wallet-2.0.1.tgz", + "integrity": "sha512-WpvFIOYh2d0HTi8ye+b62YtCOQTqsIwLqLabcDt4yoQJWMD5SiDDypd5TA1dU17Y0uAJ/oz4GIupch/PWsur2A==" }, "@cbor-extract/cbor-extract-linux-x64": { "version": "2.2.0", diff --git a/tests/govtool-frontend/playwright/package.json b/tests/govtool-frontend/playwright/package.json index a225ba91c..4ee7f6a95 100644 --- a/tests/govtool-frontend/playwright/package.json +++ b/tests/govtool-frontend/playwright/package.json @@ -25,10 +25,10 @@ "allure:serve": "npx allure serve", "test": "npx playwright test", "format": "prettier . --write", - "generate-wallets": "ts-node ./generate_wallets.ts 11" + "generate-wallets": "ts-node ./generate_wallets.ts 12" }, "dependencies": { - "@cardanoapi/cardano-test-wallet": "^2.0.0", + "@cardanoapi/cardano-test-wallet": "^2.0.1", "@faker-js/faker": "^8.4.1", "@noble/curves": "^1.3.0", "@noble/ed25519": "^2.0.0", diff --git a/tests/govtool-frontend/playwright/playwright.config.ts b/tests/govtool-frontend/playwright/playwright.config.ts index ada004008..3d2f36ebd 100644 --- a/tests/govtool-frontend/playwright/playwright.config.ts +++ b/tests/govtool-frontend/playwright/playwright.config.ts @@ -57,8 +57,8 @@ export default defineConfig({ dependencies: environments.ci ? ["faucet setup"] : [], }, { - name: "proposal setup", - testMatch: "**/proposal.setup.ts", + name: "governance-action setup", + testMatch: "**/governance-action.setup.ts", dependencies: environments.ci ? ["faucet setup"] : [], }, { @@ -73,11 +73,11 @@ export default defineConfig({ dependencies: environments.ci ? ["auth setup", "wallet bootstrap"] : [], }, { - name: "proposal", + name: "proposal submission", use: { ...devices["Desktop Chrome"] }, - testMatch: "**/*.proposal.spec.ts", + testMatch: "**/*.ga.spec.ts", dependencies: environments.ci - ? ["auth setup", "wallet bootstrap", "proposal setup"] + ? ["wallet bootstrap", "governance-action setup", "auth setup"] : [], }, { @@ -109,7 +109,7 @@ export default defineConfig({ "**/*.loggedin.spec.ts", "**/*.dRep.spec.ts", "**/*.tx.spec.ts", - "**/*.proposal.spec.ts", + "**/*.ga.spec.ts", ], }, { @@ -120,7 +120,7 @@ export default defineConfig({ "**/*.dRep.spec.ts", "**/*.delegation.spec.ts", "**/*.tx.spec.ts", - "**/*.proposal.spec.ts", + "**/*.ga.spec.ts", "**/walletConnect.spec.ts", ], }, diff --git a/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.loggedin.spec.ts b/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.loggedin.spec.ts index b96e62322..3bc367892 100644 --- a/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.loggedin.spec.ts +++ b/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.loggedin.spec.ts @@ -17,7 +17,8 @@ import { createNewPageWithWallet } from "@helpers/page"; import DRepDirectoryPage from "@pages/dRepDirectoryPage"; import EditDRepPage from "@pages/editDRepPage"; import ProposalDiscussionPage from "@pages/proposalDiscussionPage"; -import { expect } from "@playwright/test"; +import { expect, Page } from "@playwright/test"; +import { valid as mockValid, invalid as mockInvalid } from "@mock/index"; test.beforeEach(async () => { await setAllureEpic("6. Miscellaneous"); @@ -109,28 +110,59 @@ test.describe("Logged in user", () => { }) => { await page.goto("/"); await page.getByTestId("proposal-discussion-link").click(); - - await expect( - page.getByText( - "Hey, setup your usernameUsername cannot be changed in the Future. Some subtext" - ) - ).toBeVisible(); //BUG Add modal testid instead should be username-modal + await page.getByRole("button", { name: "Verify your identity" }).click(); // BUG: Test id missing + await expect(page.getByText("Hey, setup your usernameBy")).toBeVisible(); //BUG Add modal testid instead should be username-modal await expect(page.getByLabel("Username *")).toBeVisible(); // BUG use testid instead }); }); test.describe("Temporary user", () => { - test("6J. Should add a username.", async ({ page, browser }) => { + let userPage: Page; + let proposalDiscussionPage: ProposalDiscussionPage; + + test.beforeEach(async ({ page, browser }) => { const wallet = (await ShelleyWallet.generate()).json(); const tempUserAuth = await createTempUserAuth(page, wallet); - const userPage = await createNewPageWithWallet(browser, { + userPage = await createNewPageWithWallet(browser, { storageState: tempUserAuth, wallet, }); - const proposalDiscussionPage = new ProposalDiscussionPage(userPage); + proposalDiscussionPage = new ProposalDiscussionPage(userPage); await proposalDiscussionPage.goto(); - await proposalDiscussionPage.setUsername(faker.internet.userName()); + await proposalDiscussionPage.verifyIdentityBtn.click(); + }); + + test("6J. Should add a username.", async () => { + await proposalDiscussionPage.setUsername( + faker.internet.userName().toLowerCase() + ); + }); + + test("6K. Should accept valid username.", async () => { + for (let i = 0; i < 100; i++) { + await userPage + .getByLabel("Username *") + .fill(mockValid.username().toLowerCase()); + + await expect( + userPage.getByText("Invalid username. Only lower") + ).not.toBeVisible(); + await expect(userPage.getByTestId("proceed-button")).toBeEnabled(); + } + }); + + test("6L. Should reject invalid username.", async () => { + for (let i = 0; i < 100; i++) { + await userPage + .getByLabel("Username *") + .fill(mockInvalid.username().toLowerCase()); + + await expect( + userPage.getByText("Invalid username. Only lower") + ).toBeVisible(); + await expect(userPage.getByTestId("proceed-button")).toBeDisabled(); + } }); }); diff --git a/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.spec.ts b/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.spec.ts index c574c8696..55e6339be 100644 --- a/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.spec.ts +++ b/tests/govtool-frontend/playwright/tests/6-miscellaneous/miscellaneous.spec.ts @@ -1,12 +1,14 @@ import { DELEGATION_DOC_URL, DIRECT_VOTER_DOC_URL, - REGISTER_DREP_DOC_URL, - GOVERNANCE_ACTION_DOC_URL, - PROPOSE_GOVERNANCE_ACTION_DOC_URL, FAQS_DOC_URL, GUIDES_DOC_URL, + HELP_DOC_URL, + PRIVACY_POLICY, + REGISTER_DREP_DOC_URL, + TERMS_AND_CONDITIONS, } from "@constants/docsUrl"; +import { faker } from "@faker-js/faker"; import { test } from "@fixtures/walletExtension"; import { setAllureEpic } from "@helpers/allure"; import { isMobile, openDrawer } from "@helpers/mobile"; @@ -77,3 +79,155 @@ test("6D. Should open Sanchonet docs in a new tab when clicking `Learn More` on ]); await expect(directVoterLearnMorepage).toHaveURL(DIRECT_VOTER_DOC_URL); }); + +test("6M. Should navigate between footer links", async ({ page, context }) => { + await page.goto("/"); + + const [privacyPolicy] = await Promise.all([ + context.waitForEvent("page"), + page.getByTestId("privacy-policy-footer-link").click(), + ]); + await expect(privacyPolicy).toHaveURL(PRIVACY_POLICY); + + const [termsAndConditions] = await Promise.all([ + context.waitForEvent("page"), + page.getByTestId("term-of-service-footer-link").click(), + ]); + await expect(termsAndConditions).toHaveURL(TERMS_AND_CONDITIONS); + + const [helpUrl] = await Promise.all([ + context.waitForEvent("page"), + page.getByTestId("help-footer-button").click(), + ]); + await expect(helpUrl).toHaveURL(HELP_DOC_URL); +}); + +test.describe("User Snap", () => { + test.beforeEach(async ({ page }) => { + await page.goto("/"); + await page.waitForTimeout(2_000); // wait until page load properly + + await page.getByTestId("feedback-footer-button").click(); + }); + + test("6N. Should open feedback modal", async ({ page }) => { + await expect(page.getByLabel("Usersnap widget")).toBeVisible(); + await expect( + page.getByRole("button", { + name: "Report an issue Something", + }) + ).toBeVisible(); + await expect( + page.getByRole("button", { + name: "Idea or new feature Let us", + }) + ).toBeVisible(); + }); + + test("6O. Should verify a bug report form", async ({ page }) => { + await page + .getByRole("button", { + name: "Report an issue Something", + }) + .click(); + + await expect( + page.getByRole("heading", { name: "Report a bug" }) + ).toBeVisible(); + await expect(page.getByPlaceholder("Your feedback")).toBeVisible(); + await expect(page.getByText("Drag & drop or Browse")).toBeVisible(); + await expect(page.getByPlaceholder("someone@something.com")).toBeVisible(); + await expect(page.getByLabel("Take screenshot")).toBeVisible(); + await expect(page.getByLabel("Record")).toBeVisible(); + await expect(page.getByRole("button", { name: "Submit" })).toBeVisible(); + }); + + test("6P. Should verify feature form", async ({ page }) => { + await page + .getByRole("button", { + name: "Idea or new feature Let us", + }) + .click(); + + await expect( + page.getByRole("heading", { name: "Idea or new feature" }) + ).toBeVisible(); + await expect( + page.getByPlaceholder("Example: New navigation") + ).toBeVisible(); + await expect(page.getByLabel("Any additional details")).toBeVisible(); + await expect(page.getByLabel("Any additional details")).toBeVisible(); + await expect(page.getByText("Drag & drop or Browse")).toBeVisible(); + await expect(page.getByPlaceholder("someone@something.com")).toBeVisible(); + await expect(page.getByLabel("Take screenshot")).toBeVisible(); + await expect(page.getByLabel("Record")).toBeVisible(); + await expect(page.getByRole("button", { name: "Submit" })).toBeVisible(); + }); + + test.describe("Feedback Tests", () => { + const attachmentInputSelector = "input[type=file]"; + const feedbackApiUrl = + "https://widget.usersnap.com/api/widget/xhrrpc?submit_feedback"; + const mockAttachmentPath = "./lib/_mock/mockAttachment.png"; + + test("6Q. Should report an issue", async ({ page }) => { + // Intercept Usersnap submit API + await page.route(feedbackApiUrl, async (route) => + route.fulfill({ + status: 200, + }) + ); + + await page + .getByRole("button", { + name: "Report an issue Something", + }) + .click(); + + await page + .getByPlaceholder("Your feedback") + .fill(faker.lorem.paragraph(2)); + await page.setInputFiles(attachmentInputSelector, [mockAttachmentPath]); + await page + .getByPlaceholder("someone@something.com") + .fill(faker.internet.email()); + + await page.getByRole("button", { name: "Submit" }).click(); + + await expect(page.getByText("Feedback was not submitted,")).toBeVisible(); + }); + + test("6R. Should submit an idea or new feature", async ({ page }) => { + // Intercept Usersnap submit API + await page.route(feedbackApiUrl, async (route) => + route.fulfill({ + status: 200, + }) + ); + + await page + .getByRole("button", { + name: "Idea or new feature Let us", + }) + .click(); + + await page + .getByPlaceholder("Example: New navigation") + .fill(faker.lorem.words(4)); + await page + .getByLabel("Please summarize your idea or") + .fill(faker.lorem.paragraph(2)); + await page + .getByLabel("Any additional details") + .fill(faker.lorem.paragraph(2)); + await page.setInputFiles(attachmentInputSelector, [mockAttachmentPath]); + await page + .getByPlaceholder("someone@something.com") + .fill(faker.internet.email()); + + await page.getByRole("button", { name: "Submit" }).click(); + + await expect(page.getByText("Feedback was not submitted,")).toBeVisible(); + }); + }); +}); diff --git a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmissionFunctionality.proposal.spec.ts b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts similarity index 52% rename from tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmissionFunctionality.proposal.spec.ts rename to tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts index 1cbf2d8ef..6136de565 100644 --- a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmissionFunctionality.proposal.spec.ts +++ b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.ga.spec.ts @@ -1,19 +1,23 @@ import environments from "@constants/environments"; import { createTempUserAuth } from "@datafactory/createAuth"; -import { test } from "@fixtures/walletExtension"; +import { faker } from "@faker-js/faker"; +import { test } from "@fixtures/proposal"; import { setAllureEpic } from "@helpers/allure"; import { createNewPageWithWallet } from "@helpers/page"; import { waitForTxConfirmation } from "@helpers/transaction"; +import ProposalDiscussionPage from "@pages/proposalDiscussionPage"; import ProposalSubmissionPage from "@pages/proposalSubmissionPage"; import { expect } from "@playwright/test"; -import { IProposalForm, ProposalType } from "@types"; import walletManager from "lib/walletManager"; test.beforeEach(async () => { await setAllureEpic("7. Proposal submission"); }); -test("7H. should submit a proposal", async ({ page, browser }, testInfo) => { +test("7H. Should submit a proposal as governance action", async ({ + page, + browser, +}, testInfo) => { test.setTimeout(testInfo.timeout + environments.txTimeOut); const wallet = await walletManager.popWallet("proposalSubmission"); @@ -25,20 +29,32 @@ test("7H. should submit a proposal", async ({ page, browser }, testInfo) => { wallet, }); + const proposalDiscussionPage = new ProposalDiscussionPage(userPage); + await proposalDiscussionPage.goto(); + await proposalDiscussionPage.verifyIdentityBtn.click(); + + await proposalDiscussionPage.setUsername( + faker.internet.userName().toLowerCase() + ); + const proposalSubmissionPage = new ProposalSubmissionPage(userPage); await proposalSubmissionPage.goto(); - await userPage.getByTestId(`${ProposalType.info}-radio`).click(); - await proposalSubmissionPage.continueBtn.click(); + await proposalSubmissionPage.createProposal(); + + await userPage.getByTestId("submit-as-GA-button").click(); - const proposal: IProposalForm = - proposalSubmissionPage.generateValidProposalFormFields(ProposalType.info); + await userPage.click("input#submission-checkbox"); // BUG missing test id + proposalSubmissionPage.continueBtn.click(); - await proposalSubmissionPage.register({ ...proposal }); + await proposalSubmissionPage.fillUpValidMetadata(); await expect(proposalSubmissionPage.registrationSuccessModal).toBeVisible({ timeout: 10_000, }); + await expect(page.getByTestId("ga-submitted-modal-title")).toHaveText( + /governance action submitted!/i + ); - await waitForTxConfirmation(userPage); + await waitForTxConfirmation(page); }); diff --git a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.spec.ts b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.spec.ts index a78cbd007..943887729 100644 --- a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.spec.ts +++ b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmission.loggedin.spec.ts @@ -1,279 +1,410 @@ -import { user01Wallet } from "@constants/staticWallets"; +import { proposal01Wallet } from "@constants/staticWallets"; +import { createTempUserAuth } from "@datafactory/createAuth"; import { faker } from "@faker-js/faker"; -import { test } from "@fixtures/walletExtension"; +import { test } from "@fixtures/proposal"; import { setAllureEpic } from "@helpers/allure"; import { ShelleyWallet } from "@helpers/crypto"; -import { invalid } from "@mock/index"; +import { createNewPageWithWallet } from "@helpers/page"; +import { invalid, valid } from "@mock/index"; +import ProposalDiscussionDetailsPage from "@pages/proposalDiscussionDetailsPage"; +import ProposalDiscussionPage from "@pages/proposalDiscussionPage"; import ProposalSubmissionPage from "@pages/proposalSubmissionPage"; -import { expect } from "@playwright/test"; -import { IProposalForm, ProposalType } from "@types"; -import { bech32 } from "bech32"; - -test.use({ storageState: ".auth/user01.json", wallet: user01Wallet }); +import { Page, expect } from "@playwright/test"; +import { ProposalCreateRequest, ProposalType } from "@types"; test.beforeEach(async () => { await setAllureEpic("7. Proposal submission"); }); -test.describe("Accept valid data", () => { - Object.values(ProposalType).map((type: ProposalType, index) => { - test(`7E_${index + 1}. Should accept valid data in ${type.toLowerCase()} proposal form`, async ({ - page, - }) => { - test.slow(); // Brute-force testing with 100 random data +test.describe("Proposal created logged state", () => { + test.use({ storageState: ".auth/proposal01.json", wallet: proposal01Wallet }); + test("7B. Should access proposal creation page", async ({ page }) => { + await page.goto("/"); + await page.getByTestId("propose-governance-actions-button").click(); - const proposalSubmissionPage = new ProposalSubmissionPage(page); + await expect( + page.getByText("Create a Governance Action", { exact: true }) + ).toBeVisible(); + }); - await proposalSubmissionPage.goto(); + test.describe("Accept valid data", () => { + Object.values(ProposalType).map((type: ProposalType, index) => { + test(`7E_${index + 1}. Should accept valid data in ${type.toLowerCase()} proposal form`, async ({ + page, + }) => { + test.slow(); // Brute-force testing with 100 random data - await page.getByTestId(`${type}-radio`).click(); - await proposalSubmissionPage.continueBtn.click(); + const proposalSubmissionPage = new ProposalSubmissionPage(page); - for (let i = 0; i < 100; i++) { - const randomBytes = new Uint8Array(10); - const bech32Address = bech32.encode("addr_test", randomBytes); - const formFields: IProposalForm = - proposalSubmissionPage.generateValidProposalFormFields( - type, - bech32Address - ); - await proposalSubmissionPage.validateForm(formFields); - } + await proposalSubmissionPage.goto(); - for (let i = 0; i < 7; i++) { - await expect(proposalSubmissionPage.addLinkBtn).toBeVisible(); + await proposalSubmissionPage.governanceActionType.click(); + await page.getByRole("option", { name: type }).click(); await proposalSubmissionPage.addLinkBtn.click(); - } - await expect(proposalSubmissionPage.addLinkBtn).toBeHidden(); + for (let i = 0; i < 100; i++) { + const rewardAddressBech32 = ( + await ShelleyWallet.generate() + ).rewardAddressBech32(0); + const formFields: ProposalCreateRequest = + proposalSubmissionPage.generateValidProposalFormFields( + type, + false, + rewardAddressBech32 + ); + await proposalSubmissionPage.validateForm(formFields); + } + + for (let i = 0; i < 6; i++) { + await expect(proposalSubmissionPage.addLinkBtn).toBeVisible(); + await proposalSubmissionPage.addLinkBtn.click(); + } + + await expect(proposalSubmissionPage.addLinkBtn).toBeHidden(); + }); }); }); -}); -test.describe("Reject invalid data", () => { - Object.values(ProposalType).map((type: ProposalType, index) => { - test(`7F_${index + 1}. Should reject invalid data in ${type.toLowerCase()} Proposal form`, async ({ - page, - }) => { - test.slow(); // Brute-force testing with 100 random data + test.describe("Reject invalid data", () => { + Object.values(ProposalType).map((type: ProposalType, index) => { + test(`7F_${index + 1}. Should reject invalid data in ${type.toLowerCase()} Proposal form`, async ({ + page, + }) => { + test.slow(); // Brute-force testing with 100 random data - const proposalSubmissionPage = new ProposalSubmissionPage(page); + const proposalSubmissionPage = new ProposalSubmissionPage(page); + await proposalSubmissionPage.goto(); - await proposalSubmissionPage.goto(); + await proposalSubmissionPage.governanceActionType.click(); + await page.getByRole("option", { name: type }).click(); + await proposalSubmissionPage.addLinkBtn.click(); - await page.getByTestId(`${type}-radio`).click(); - await proposalSubmissionPage.continueBtn.click(); + const formFields: ProposalCreateRequest = + proposalSubmissionPage.generateInValidProposalFormFields(type); - const formFields: IProposalForm = - proposalSubmissionPage.generateInValidProposalFormFields(type); - for (let i = 0; i < 100; i++) { - await proposalSubmissionPage.inValidateForm(formFields); - } + for (let i = 0; i < 100; i++) { + await proposalSubmissionPage.inValidateForm(formFields); + } + }); }); }); -}); -test.describe("Proposal submission check", () => { - Object.values(ProposalType).map((type: ProposalType, index) => { - test(`7G_${index + 1}. Should open wallet connection popup, when registered with proper ${type.toLowerCase()} data`, async ({ - page, - wallet, - }) => { - const proposalSubmissionPage = new ProposalSubmissionPage(page); + test.describe("Create a proposal with proper data", () => { + Object.values(ProposalType).map((type: ProposalType, index) => { + test(`7G_${index + 1}. Should create a proposal with proper ${type.toLowerCase()} data`, async ({ + page, + wallet, + }) => { + const proposalSubmissionPage = new ProposalSubmissionPage(page); + await proposalSubmissionPage.goto(); - await proposalSubmissionPage.goto(); + await proposalSubmissionPage.addLinkBtn.click(); - await page.getByTestId(`${type}-radio`).click(); - await proposalSubmissionPage.continueBtn.click(); + const walletAddressBech32 = + ShelleyWallet.fromJson(wallet).rewardAddressBech32(0); + const proposal: ProposalCreateRequest = + proposalSubmissionPage.generateValidProposalFormFields( + type, + false, + walletAddressBech32 + ); - const walletAddressBech32 = - ShelleyWallet.fromJson(wallet).rewardAddressBech32(0); + await proposalSubmissionPage.fillupForm(proposal); + await proposalSubmissionPage.continueBtn.click(); + await proposalSubmissionPage.submitBtn.click(); + + await expect(page.getByTestId("submit-as-GA-button")).toBeVisible(); + await expect(page.getByText(type, { exact: true })).toBeVisible(); + await expect(page.getByText(proposal.prop_name)).toBeVisible(); + await expect(page.getByText(proposal.prop_abstract)).toBeVisible(); + await expect(page.getByText(proposal.prop_rationale)).toBeVisible(); + await expect(page.getByText(proposal.prop_motivation)).toBeVisible(); + }); + }); + }); - const proposal: IProposalForm = - proposalSubmissionPage.generateValidProposalFormFields( - type, - walletAddressBech32 - ); - await proposalSubmissionPage.register({ ...proposal }); - await expect( - proposalSubmissionPage.registrationErrorModal.getByText( - "UTxO Balance Insufficient" - ) - ).toBeVisible(); + test.describe("Review fillup form", () => { + Object.values(ProposalType).map((type: ProposalType, index) => { + test(`7I_${index + 1}. Should valid review submission in ${type.toLowerCase()} Proposal form`, async ({ + page, + }) => { + const proposalSubmissionPage = new ProposalSubmissionPage(page); + await proposalSubmissionPage.goto(); + + await proposalSubmissionPage.addLinkBtn.click(); + + const walletAddressBech32 = + ShelleyWallet.fromJson(proposal01Wallet).rewardAddressBech32(0); + const proposal: ProposalCreateRequest = + proposalSubmissionPage.generateValidProposalFormFields( + type, + false, + walletAddressBech32 + ); + + await proposalSubmissionPage.fillupForm(proposal); + await proposalSubmissionPage.continueBtn.click(); + + await expect(page.getByText(proposal.prop_name)).toBeVisible(); + await expect(page.getByText(proposal.prop_abstract)).toBeVisible(); + await expect(page.getByText(proposal.prop_motivation)).toBeVisible(); + await expect(page.getByText(proposal.prop_rationale)).toBeVisible(); + await expect( + page.getByText(proposal.proposal_links[0].prop_link_text) + ).toBeVisible(); + + if (type === ProposalType.treasury) { + await expect( + page.getByText(proposal.prop_receiving_address) + ).toBeVisible(); + await expect( + page.getByText(proposal.prop_amount, { exact: true }) + ).toBeVisible(); + } + }); }); }); -}); -test.describe("Review fillup form", () => { - Object.values(ProposalType).map((type: ProposalType, index) => { - test(`7I_${index + 1}. Should valid review submission in ${type.toLowerCase()} Proposal form`, async ({ - page, - }) => { - const proposalSubmissionPage = new ProposalSubmissionPage(page); + test.describe("Verify Proposal form", () => { + Object.values(ProposalType).map((type: ProposalType, index) => { + test(`7D_${index + 1}. Verify ${type.toLocaleLowerCase()} proposal form`, async ({ + page, + }) => { + const proposalSubmissionPage = new ProposalSubmissionPage(page); + await proposalSubmissionPage.goto(); + + await proposalSubmissionPage.governanceActionType.click(); + await page.getByRole("option", { name: type }).click(); + + await expect(proposalSubmissionPage.titleInput).toBeVisible(); + await expect(proposalSubmissionPage.abstractInput).toBeVisible(); + await expect(proposalSubmissionPage.motivationInput).toBeVisible(); + await expect(proposalSubmissionPage.rationaleInput).toBeVisible(); + await expect(proposalSubmissionPage.addLinkBtn).toBeVisible(); + if (type === ProposalType.treasury) { + await expect( + proposalSubmissionPage.receivingAddressInput + ).toBeVisible(); + + await expect(proposalSubmissionPage.amountInput).toBeVisible(); + } + }); + }); + }); - await proposalSubmissionPage.goto(); + test.describe("proposed as a governance action", () => { + let proposalSubmissionPage: ProposalSubmissionPage; + test.beforeEach(async ({ page, proposalId }) => { + const proposalDiscussionDetailsPage = new ProposalDiscussionDetailsPage( + page + ); + await proposalDiscussionDetailsPage.goto(proposalId); - await page.getByTestId(`${type}-radio`).click(); - await proposalSubmissionPage.continueBtn.click(); + await proposalDiscussionDetailsPage.verifyIdentityBtn.click(); + await proposalDiscussionDetailsPage.submitAsGABtn.click(); - const randomBytes = new Uint8Array(10); - const bech32Address = bech32.encode("addr_test", randomBytes); + proposalSubmissionPage = new ProposalSubmissionPage(page); + await page.click("input#submission-checkbox"); // BUG missing test id + await page.getByRole("button", { name: "Continue" }).click(); + }); - const formFields: IProposalForm = - proposalSubmissionPage.generateValidProposalFormFields( - type, - bech32Address + test.describe("Metadata anchor validation", () => { + test("7J_1. Should accept valid metadata anchor on proposal submission", async ({ + page, + }) => { + test.slow(); // Brute-force testing with 100 random data + for (let i = 0; i < 100; i++) { + await proposalSubmissionPage.metadataUrlInput.fill( + faker.internet.url() + ); + await expect(page.getByText("Invalid URL")).toBeHidden(); // BUG missing test ids + } + }); + + test("7J_2. Should reject invalid metadata anchor on proposal submission", async ({ + page, + }) => { + test.slow(); // Brute-force testing with 100 random data + for (let i = 0; i < 100; i++) { + await proposalSubmissionPage.metadataUrlInput.fill(invalid.url()); + await expect(page.getByText("Invalid URL")).toBeVisible(); // BUG missing test ids + } + + const sentenceWithoutSpace = faker.lorem + .sentence(128) + .replace(/[\s.]/g, ""); + const metadataAnchorGreaterThan128Bytes = + faker.internet.url({ appendSlash: true }) + sentenceWithoutSpace; + + await proposalSubmissionPage.metadataUrlInput.fill( + metadataAnchorGreaterThan128Bytes ); - await proposalSubmissionPage.validateForm(formFields); - proposalSubmissionPage.continueBtn.click(); - await expect(page.getByText(formFields.title)).toBeVisible(); - await expect(page.getByText(formFields.abstract)).toBeVisible(); - await expect(page.getByText(formFields.motivation)).toBeVisible(); - await expect(page.getByText(formFields.rationale)).toBeVisible(); - await expect( - page.getByText(formFields.extraContentLinks[0]) - ).toBeVisible(); + await expect(page.getByText("Url must be less than 128")).toBeVisible(); // BUG missing test ids + }); + }); + + test("7K. Should reject invalid proposal metadata", async ({ page }) => { + await proposalSubmissionPage.metadataUrlInput.fill(faker.internet.url()); + await proposalSubmissionPage.submitBtn.click(); - if (type === ProposalType.treasury) { - await expect(page.getByText(formFields.receivingAddress)).toBeVisible(); - await expect(page.getByText(formFields.amount)).toBeVisible(); - } + await expect(page.getByTestId("url-error-modal-title")).toHaveText( + /the url you entered cannot be found/i + ); }); }); }); -test("7L. Should reject invalid proposal metadata", async ({ page }) => { - const invalidMetadataAnchor = "https://www.google.com"; +test.describe("Temporary proposal users", () => { + let userPage: Page; + test.beforeEach(async ({ page, browser }) => { + const wallet = (await ShelleyWallet.generate()).json(); + const tempUserAuth = await createTempUserAuth(page, wallet); - const proposalSubmissionPage = new ProposalSubmissionPage(page); - await proposalSubmissionPage.goto(); - ``; - await page.getByTestId(`${ProposalType.info}-radio`).click(); - await proposalSubmissionPage.continueBtn.click(); + userPage = await createNewPageWithWallet(browser, { + storageState: tempUserAuth, + wallet, + }); + + const proposalDiscussionPage = new ProposalDiscussionPage(userPage); + await proposalDiscussionPage.goto(); + await proposalDiscussionPage.verifyIdentityBtn.click(); - const proposal: IProposalForm = - proposalSubmissionPage.generateValidProposalFormFields(ProposalType.info); + await proposalDiscussionPage.setUsername(valid.username()); + }); - await proposalSubmissionPage.fillupForm(proposal); - await proposalSubmissionPage.continueBtn.click(); - await proposalSubmissionPage.continueBtn.click(); - await page.getByRole("checkbox").click(); - await proposalSubmissionPage.continueBtn.click(); + test.describe("Info Proposal Draft", () => { + let proposalSubmissionPage: ProposalSubmissionPage; + let proposalFormValue: ProposalCreateRequest; - await proposalSubmissionPage.metadataUrlInput.fill(invalidMetadataAnchor); - await proposalSubmissionPage.continueBtn.click(); + test.beforeEach(async () => { + proposalSubmissionPage = new ProposalSubmissionPage(userPage); + await proposalSubmissionPage.proposalCreateBtn.click(); + await proposalSubmissionPage.continueBtn.click(); - await expect(proposalSubmissionPage.registrationErrorModal).not.toHaveText( - /utxo balance insufficient/i - ); -}); + await proposalSubmissionPage.addLinkBtn.click(); + proposalFormValue = + proposalSubmissionPage.generateValidProposalFormFields( + ProposalType.info, + true + ); + await proposalSubmissionPage.fillupForm(proposalFormValue); -test.describe("Edit proposal form", () => { - Object.values(ProposalType).map((type: ProposalType, index) => { - test(`7J_${index + 1}. Should edit review submission in ${type.toLowerCase()} Proposal form`, async ({ - page, - }) => { - const proposalSubmissionPage = new ProposalSubmissionPage(page); + await proposalSubmissionPage.saveDraftBtn.click(); + await proposalSubmissionPage.closeDraftSuccessModalBtn.click(); - await proposalSubmissionPage.goto(); + await proposalSubmissionPage.proposalCreateBtn.click(); + }); - await page.getByTestId(`${type}-radio`).click(); - await proposalSubmissionPage.continueBtn.click(); + test("7C. Should list unfinished Draft ", async () => { + const getAllDrafts = await proposalSubmissionPage.getAllDrafts(); - const randomBytes = new Uint8Array(10); - const bech32Address = bech32.encode("addr_test", randomBytes); + expect(getAllDrafts.length).toBeGreaterThan(0); + }); - const formFields: IProposalForm = - proposalSubmissionPage.generateValidProposalFormFields( - type, - bech32Address - ); - await proposalSubmissionPage.validateForm(formFields); - proposalSubmissionPage.continueBtn.click(); + test("7L. Should save proposal as a draft", async () => { + const draftCard = proposalSubmissionPage.getFirstDraft(); + const draftCardAllInnerText = await (await draftCard).allInnerTexts(); - await proposalSubmissionPage.editSubmissionButton.click(); + expect(draftCardAllInnerText.includes(proposalFormValue.prop_name)); + expect(draftCardAllInnerText.includes(proposalFormValue.prop_abstract)); + }); - const newTitle = faker.person.firstName(); + test("7M_1. Should edit a info proposal draft", async ({}) => { + const newTitle = faker.lorem.sentence(6); + await proposalSubmissionPage.viewFirstDraft(); await proposalSubmissionPage.titleInput.fill(newTitle); - await proposalSubmissionPage.continueBtn.click(); - await expect(page.getByText(newTitle)).toBeVisible(); - await expect(page.getByText(formFields.abstract)).toBeVisible(); - await expect(page.getByText(formFields.motivation)).toBeVisible(); - await expect(page.getByText(formFields.rationale)).toBeVisible(); + await expect(userPage.getByText(newTitle)).toBeVisible(); + await expect( + userPage.getByText(proposalFormValue.prop_abstract) + ).toBeVisible(); + await expect( + userPage.getByText(proposalFormValue.prop_motivation) + ).toBeVisible(); + await expect( + userPage.getByText(proposalFormValue.prop_rationale) + ).toBeVisible(); await expect( - page.getByText(formFields.extraContentLinks[0]) + userPage.getByText(proposalFormValue.proposal_links[0].prop_link_text) ).toBeVisible(); + }); - if (type === ProposalType.treasury) { - await expect(page.getByText(formFields.receivingAddress)).toBeVisible(); - await expect(page.getByText(formFields.amount)).toBeVisible(); - } + test("7N. Should submit a draft proposal", async ({}) => { + await proposalSubmissionPage.viewFirstDraft(); + await proposalSubmissionPage.continueBtn.click(); + await proposalSubmissionPage.submitBtn.click(); + + await expect(userPage.getByTestId("submit-as-GA-button")).toBeVisible(); + await expect( + userPage.getByText(ProposalType.info, { exact: true }) + ).toBeVisible(); + await expect( + userPage.getByText(proposalFormValue.prop_name) + ).toBeVisible(); + await expect( + userPage.getByText(proposalFormValue.prop_abstract) + ).toBeVisible(); + await expect( + userPage.getByText(proposalFormValue.prop_rationale) + ).toBeVisible(); + await expect( + userPage.getByText(proposalFormValue.prop_motivation) + ).toBeVisible(); }); }); -}); -test("7K_1. Should accept valid metadata anchor on proposal submission", async ({ - page, -}) => { - const invalidMetadataAnchor = "https://www.google.com"; - - const proposalSubmissionPage = new ProposalSubmissionPage(page); - await proposalSubmissionPage.goto(); - ``; - await page.getByTestId(`${ProposalType.info}-radio`).click(); - await proposalSubmissionPage.continueBtn.click(); - - const proposal: IProposalForm = - proposalSubmissionPage.generateValidProposalFormFields(ProposalType.info); - - await proposalSubmissionPage.fillupForm(proposal); - await proposalSubmissionPage.continueBtn.click(); - await proposalSubmissionPage.continueBtn.click(); - await page.getByRole("checkbox").click(); - await proposalSubmissionPage.continueBtn.click(); - - for (let i = 0; i < 100; i++) { - await proposalSubmissionPage.metadataUrlInput.fill(faker.internet.url()); - await expect(page.getByTestId("invalid-url-error")).toBeHidden(); - } -}); - -test("7K_2. Should reject invalid metadata anchor on proposal submission", async ({ - page, -}) => { - const invalidMetadataAnchor = "https://www.google.com"; + test.describe("Treasury Proposal Draft", () => { + let proposalSubmissionPage: ProposalSubmissionPage; + let proposalFormValue: ProposalCreateRequest; - const proposalSubmissionPage = new ProposalSubmissionPage(page); - await proposalSubmissionPage.goto(); - ``; - await page.getByTestId(`${ProposalType.info}-radio`).click(); - await proposalSubmissionPage.continueBtn.click(); + test.beforeEach(async () => { + proposalSubmissionPage = new ProposalSubmissionPage(userPage); + await proposalSubmissionPage.goto(); - const proposal: IProposalForm = - proposalSubmissionPage.generateValidProposalFormFields(ProposalType.info); + await proposalSubmissionPage.addLinkBtn.click(); + proposalFormValue = + proposalSubmissionPage.generateValidProposalFormFields( + ProposalType.treasury, + true, + ShelleyWallet.fromJson(proposal01Wallet).rewardAddressBech32(0) + ); + await proposalSubmissionPage.fillupForm(proposalFormValue); - await proposalSubmissionPage.fillupForm(proposal); - await proposalSubmissionPage.continueBtn.click(); - await proposalSubmissionPage.continueBtn.click(); - await page.getByRole("checkbox").click(); - await proposalSubmissionPage.continueBtn.click(); + await proposalSubmissionPage.saveDraftBtn.click(); + await proposalSubmissionPage.closeDraftSuccessModalBtn.click(); - for (let i = 0; i < 100; i++) { - await proposalSubmissionPage.metadataUrlInput.fill(invalid.url()); - await expect(page.getByTestId("invalid-url-error")).toBeVisible(); - } + await proposalSubmissionPage.proposalCreateBtn.click(); + }); - const sentenceWithoutSpace = faker.lorem.sentence(128).replace(/[\s.]/g, ""); - const metadataAnchorGreaterThan128Bytes = - faker.internet.url({ appendSlash: true }) + sentenceWithoutSpace; + test("7M_2. Should edit a treasury proposal draft", async () => { + const newTitle = faker.lorem.sentence(6); - await proposalSubmissionPage.metadataUrlInput.fill( - metadataAnchorGreaterThan128Bytes - ); + await proposalSubmissionPage.viewFirstDraft(); + await proposalSubmissionPage.titleInput.fill(newTitle); + await proposalSubmissionPage.continueBtn.click(); - await expect(page.getByTestId("invalid-url-error")).toBeVisible(); + await expect(userPage.getByText(newTitle)).toBeVisible(); + await expect( + userPage.getByText(proposalFormValue.prop_abstract) + ).toBeVisible(); + await expect( + userPage.getByText(proposalFormValue.prop_motivation) + ).toBeVisible(); + await expect( + userPage.getByText(proposalFormValue.prop_rationale) + ).toBeVisible(); + await expect( + userPage.getByText(proposalFormValue.prop_receiving_address) + ).toBeVisible(); + await expect( + userPage.getByText(proposalFormValue.prop_amount) + ).toBeVisible(); + await expect( + userPage.getByText(proposalFormValue.proposal_links[0].prop_link_text) + ).toBeVisible(); + }); + }); }); diff --git a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmissionVisibility.loggedin.spec.ts b/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmissionVisibility.loggedin.spec.ts deleted file mode 100644 index b5e850130..000000000 --- a/tests/govtool-frontend/playwright/tests/7-proposal-submission/proposalSubmissionVisibility.loggedin.spec.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { user01Wallet } from "@constants/staticWallets"; -import { test } from "@fixtures/walletExtension"; -import { setAllureEpic } from "@helpers/allure"; -import ProposalSubmissionPage from "@pages/proposalSubmissionPage"; -import { expect } from "@playwright/test"; -import { ProposalType } from "@types"; - -test.beforeEach(async () => { - await setAllureEpic("7. Proposal submission"); -}); - -test.use({ storageState: ".auth/user01.json", wallet: user01Wallet }); - -test("7B. Should access proposal submission page", async ({ page }) => { - await page.goto("/"); - await page.getByTestId("propose-governance-actions-button").click(); - - await expect( - page.getByText("Create a Governance Action", { exact: true }) - ).toBeVisible(); -}); - -test("7C. Should list governance action types", async ({ page }) => { - const proposalSubmissionPage = new ProposalSubmissionPage(page); - await proposalSubmissionPage.goto(); - - await expect(proposalSubmissionPage.infoRadioButton).toBeVisible(); - await expect(proposalSubmissionPage.treasuryRadioButton).toBeVisible(); -}); - -test.describe("Verify Proposal form", () => { - Object.values(ProposalType).map((type: ProposalType, index) => { - test(`7D_${index + 1}. Verify ${type.toLocaleLowerCase()} proposal form`, async ({ - page, - }) => { - const proposalSubmissionPage = new ProposalSubmissionPage(page); - await proposalSubmissionPage.goto(); - - await page.getByTestId(`${type}-radio`).click(); - await proposalSubmissionPage.continueBtn.click(); - - await expect(proposalSubmissionPage.titleInput).toBeVisible(); - await expect(proposalSubmissionPage.abstractInput).toBeVisible(); - await expect(proposalSubmissionPage.motivationInput).toBeVisible(); - await expect(proposalSubmissionPage.rationaleInput).toBeVisible(); - await expect(proposalSubmissionPage.addLinkBtn).toBeVisible(); - if (type === ProposalType.treasury) { - await expect( - proposalSubmissionPage.receivingAddressInput - ).toBeVisible(); - - await expect(proposalSubmissionPage.amountInput).toBeVisible(); - } - }); - }); -}); diff --git a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.loggedin.spec.ts b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.loggedin.spec.ts index 9851d247f..d2a8d8fe8 100644 --- a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.loggedin.spec.ts +++ b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.loggedin.spec.ts @@ -1,17 +1,25 @@ -import { proposal01Wallet, user01Wallet } from "@constants/staticWallets"; +import { + proposal01Wallet, + proposal02Wallet, + user01Wallet, +} from "@constants/staticWallets"; import { createTempUserAuth } from "@datafactory/createAuth"; import { faker } from "@faker-js/faker"; import { test } from "@fixtures/proposal"; import { ShelleyWallet } from "@helpers/crypto"; import { createNewPageWithWallet } from "@helpers/page"; import ProposalDiscussionDetailsPage from "@pages/proposalDiscussionDetailsPage"; -import ProposalDiscussionPage from "@pages/proposalDiscussionPage"; import { Page, expect } from "@playwright/test"; +import { setAllureEpic } from "@helpers/allure"; + +test.beforeEach(async () => { + await setAllureEpic("8. Proposal Discussion Forum"); +}); test.describe("Proposal created logged in state", () => { test.use({ - storageState: ".auth/user01.json", - wallet: user01Wallet, + storageState: ".auth/proposal02.json", + wallet: proposal02Wallet, }); let proposalDiscussionDetailsPage: ProposalDiscussionDetailsPage; @@ -19,7 +27,8 @@ test.describe("Proposal created logged in state", () => { test.beforeEach(async ({ page, proposalId }) => { proposalDiscussionDetailsPage = new ProposalDiscussionDetailsPage(page); await proposalDiscussionDetailsPage.goto(proposalId); - await proposalDiscussionDetailsPage.closeUsernamePrompt(); + + await proposalDiscussionDetailsPage.verifyIdentityBtn.click(); }); test("8G. Should display the proper likes and dislikes count", async ({ @@ -27,7 +36,7 @@ test.describe("Proposal created logged in state", () => { }) => { await proposalDiscussionDetailsPage.likeBtn.click(); await page.waitForTimeout(2_000); - await expect(page.getByText("10")).toBeVisible(); + await expect(page.getByText("10", { exact: true })).toBeVisible(); await proposalDiscussionDetailsPage.dislikeBtn.click(); await page.waitForTimeout(2_000); @@ -49,16 +58,9 @@ test.describe("Proposal created logged in state", () => { ); }); - test("8M. Should comment anonymously if a username is not set", async ({ - page, - }) => { - const randComment = faker.lorem.paragraph(2); - await proposalDiscussionDetailsPage.addComment(randComment); - - await expect(page.getByText(randComment)).toBeVisible(); - }); - test("8N. Should reply to comments", async ({ page }) => { + test.slow(); + const randComment = faker.lorem.paragraph(2); const randReply = faker.lorem.paragraph(2); @@ -78,16 +80,14 @@ test.describe("Proposal created with poll enabled (user auth)", () => { let proposalDiscussionDetailsPage: ProposalDiscussionDetailsPage; - test.beforeEach(async ({ page, proposalId, browser }) => { - const proposalPage = await createNewPageWithWallet(browser, { - storageState: ".auth/proposal01.json", - wallet: proposal01Wallet, - }); - + test.beforeEach(async ({ page, proposalId }) => { proposalDiscussionDetailsPage = new ProposalDiscussionDetailsPage(page); await proposalDiscussionDetailsPage.goto(proposalId); + await proposalDiscussionDetailsPage.verifyIdentityBtn.click(); + await proposalDiscussionDetailsPage.closeUsernamePrompt(); }); + test("8Q. Should vote on poll.", async ({ page }) => { const pollVotes = ["Yes", "No"]; const choice = Math.floor(Math.random() * pollVotes.length); @@ -138,33 +138,6 @@ test.describe("Proposal created logged out state", () => { wallet, }); }); - - test("8O. Should update anonymous username to set username in comments", async ({ - proposalId, - }) => { - test.slow(); - - const proposalDiscussionDetailsPage = new ProposalDiscussionDetailsPage( - userPage - ); - await proposalDiscussionDetailsPage.goto(proposalId); - await proposalDiscussionDetailsPage.closeUsernamePrompt(); - - const randComment = faker.lorem.paragraph(2); - await proposalDiscussionDetailsPage.addComment(randComment); - - await expect(userPage.getByText(/anonymous/i)).toBeVisible(); - - const proposalDiscussionPage = new ProposalDiscussionPage(userPage); - await proposalDiscussionPage.goto(); - - const userName = faker.internet.userName(); - await proposalDiscussionPage.setUsername(userName); - await proposalDiscussionDetailsPage.goto(proposalId); - - await expect(userPage.getByText(/anonymous/i)).not.toBeVisible(); - await expect(userPage.getByText(userName)).toBeVisible(); - }); }); test.describe("Proposal created with poll enabled (proposal auth)", () => { @@ -174,29 +147,34 @@ test.describe("Proposal created with poll enabled (proposal auth)", () => { pollEnabled: true, }); - let proposalDiscussionDetailsPage: ProposalDiscussionDetailsPage; + let ownerProposalDiscussionDetailsPage: ProposalDiscussionDetailsPage; test.beforeEach(async ({ browser, proposalId }) => { const proposalPage = await createNewPageWithWallet(browser, { storageState: ".auth/proposal01.json", wallet: proposal01Wallet, }); - proposalDiscussionDetailsPage = new ProposalDiscussionDetailsPage( + ownerProposalDiscussionDetailsPage = new ProposalDiscussionDetailsPage( proposalPage ); - proposalDiscussionDetailsPage.goto(proposalId); + ownerProposalDiscussionDetailsPage.goto(proposalId); + await ownerProposalDiscussionDetailsPage.verifyIdentityBtn.click(); }); test("8P. Should add poll on own proposal", async ({}) => { - await expect(proposalDiscussionDetailsPage.addPollBtn).not.toBeVisible(); + await expect( + ownerProposalDiscussionDetailsPage.addPollBtn + ).not.toBeVisible(); }); test("8R. Should disable voting after cancelling the poll with the current poll result.", async ({ page, }) => { - await proposalDiscussionDetailsPage.closePollBtn.click(); - await proposalDiscussionDetailsPage.closePollYesBtn.click(); - await expect(proposalDiscussionDetailsPage.closePollBtn).not.toBeVisible(); + await ownerProposalDiscussionDetailsPage.closePollBtn.click(); + await ownerProposalDiscussionDetailsPage.closePollYesBtn.click(); + await expect( + ownerProposalDiscussionDetailsPage.closePollBtn + ).not.toBeVisible(); // user const userProposalDetailsPage = new ProposalDiscussionDetailsPage(page); diff --git a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts index d00bb4f01..c592ce381 100644 --- a/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts +++ b/tests/govtool-frontend/playwright/tests/8-proposal-discussion/proposalDiscussion.spec.ts @@ -1,3 +1,4 @@ +import environments from "@constants/environments"; import { faker } from "@faker-js/faker"; import { test } from "@fixtures/proposal"; import { setAllureEpic } from "@helpers/allure"; @@ -8,9 +9,17 @@ import { expect } from "@playwright/test"; const mockProposal = require("../../lib/_mock/proposal.json"); const mockPoll = require("../../lib/_mock/proposalPoll.json"); const mockComments = require("../../lib/_mock/proposalComments.json"); +const mockInfoProposedGA = require("../../lib/_mock/infoProposedGAs.json"); -test.beforeEach(() => { - setAllureEpic("Proposal Discussion Forum"); +const PROPOSAL_FILTERS = [ + "Info", + "Treasury", + "Submitted for vote ", + "Active proposal", +]; + +test.beforeEach(async () => { + await setAllureEpic("8. Proposal Discussion Forum"); }); test("8A. Should access proposed governance actions in disconnected state", async ({ @@ -19,21 +28,52 @@ test("8A. Should access proposed governance actions in disconnected state", asyn const proposalDiscussionPage = new ProposalDiscussionPage(page); await proposalDiscussionPage.goto(); - await expect(page.getByText(/Proposed Governance Actions/i)).toHaveCount(2); + await expect(page.getByText(/Proposed Governance Actions/i)).toHaveCount(1); }); -test("8B. Should filter and sort the list of proposed governance actions.", async ({ - page, -}) => { - const proposalDiscussionPage = new ProposalDiscussionPage(page); - await proposalDiscussionPage.goto(); +test.describe("Filter and sort proposals", () => { + let proposalDiscussionPage: ProposalDiscussionPage; - await proposalDiscussionPage.filterBtn.click(); - await proposalDiscussionPage.infoRadio.click(); + test.beforeEach(async ({ page }) => { + proposalDiscussionPage = new ProposalDiscussionPage(page); + await proposalDiscussionPage.goto(); + }); + + test("8B_1. Should filter the list of proposed governance actions.", async () => { + test.slow(); + + await proposalDiscussionPage.filterBtn.click(); + + // Single filter + for (const filter of PROPOSAL_FILTERS) { + await proposalDiscussionPage.filterProposalByNames([filter]); + await proposalDiscussionPage.validateFilters([filter]); + await proposalDiscussionPage.unFilterProposalByNames([filter]); + } + + // Multiple filters + const multipleFilters = [...PROPOSAL_FILTERS]; + while (multipleFilters.length > 1) { + await proposalDiscussionPage.filterProposalByNames(multipleFilters); + await proposalDiscussionPage.validateFilters(multipleFilters); + await proposalDiscussionPage.unFilterProposalByNames(multipleFilters); + multipleFilters.pop(); + } + }); - await expect(page.getByText("Treasury")).toHaveCount(1); + test("8B_2. Should sort the list of proposed governance actions.", async () => { + await proposalDiscussionPage.sortBtn.click(); + + await proposalDiscussionPage.sortAndValidate( + "asc", + (p1, p2) => p1.attributes.createdAt <= p2.attributes.createdAt + ); - await proposalDiscussionPage.treasuryRadio.click(); + await proposalDiscussionPage.sortAndValidate( + "desc", + (p1, p2) => p1.attributes.createdAt >= p2.attributes.createdAt + ); + }); }); test("8C. Should search the list of proposed governance actions.", async ({ @@ -55,12 +95,22 @@ test("8C. Should search the list of proposed governance actions.", async ({ test("8D.Should show the view-all categorized proposed governance actions.", async ({ page, }) => { + await page.route("**/api/proposals?**", async (route) => { + return route.fulfill({ + body: JSON.stringify(mockInfoProposedGA), + }); + }); + const proposalDiscussionPage = new ProposalDiscussionPage(page); await proposalDiscussionPage.goto(); await proposalDiscussionPage.showAllBtn.click(); - await expect(proposalDiscussionPage.showLessBtn).toBeVisible(); + const proposalCards = await proposalDiscussionPage.getAllProposals(); + + for (const proposalCard of proposalCards) { + await expect(proposalCard.getByText("Info", { exact: true })).toBeVisible(); + } }); test("8H. Should disable proposal interaction on a disconnected state.", async ({ @@ -113,7 +163,7 @@ test.describe("Mocked proposal", () => { ); proposalDiscussionDetailsPage = new ProposalDiscussionDetailsPage(page); - await proposalDiscussionDetailsPage.goto(10); + await proposalDiscussionDetailsPage.goto(mockProposal.data.id); }); test("8E. Should share proposed governance action", async ({ @@ -122,12 +172,16 @@ test.describe("Mocked proposal", () => { }) => { await context.grantPermissions(["clipboard-read", "clipboard-write"]); - await page.getByTestId("share-button").click(); - await expect(page.getByText("Copied to clipboard")).toBeVisible(); + await page.locator("#share-button").click(); // BUG + await page.getByRole("button").click(); // BUG + await expect(page.getByText("Link copied")).toBeVisible(); // Bug + const copiedTextDRepDirectory = await page.evaluate(() => navigator.clipboard.readText() ); - expect(copiedTextDRepDirectory).toEqual(mockProposal.data.id); + const expectedCopyUrl = `${environments.frontendUrl}/proposal_discussion/${mockProposal.data.id}`; + + expect(copiedTextDRepDirectory).toEqual(expectedCopyUrl); }); test("8I. Should disable poll voting functionality.", async () => { @@ -138,8 +192,8 @@ test.describe("Mocked proposal", () => { }); test("8F. Should display all comments with count indication.", async () => { - await expect(proposalDiscussionDetailsPage.commentsCount).toHaveText( - mockProposal.data.attributes.prop_comments_number + await expect(proposalDiscussionDetailsPage.commentCount).toHaveText( + mockProposal.data.attributes.prop_comments_number.toString() ); }); }); diff --git a/tests/govtool-frontend/playwright/tests/auth.setup.ts b/tests/govtool-frontend/playwright/tests/auth.setup.ts index 043004498..4bcceb339 100644 --- a/tests/govtool-frontend/playwright/tests/auth.setup.ts +++ b/tests/govtool-frontend/playwright/tests/auth.setup.ts @@ -10,6 +10,7 @@ import { dRep01Wallet, dRep02Wallet, proposal01Wallet, + proposal02Wallet, user01Wallet, } from "@constants/staticWallets"; import { faker } from "@faker-js/faker"; @@ -32,6 +33,7 @@ const adaHolder06AuthFile = ".auth/adaHolder06.json"; const user01AuthFile = ".auth/user01.json"; const proposal01AuthFile = ".auth/proposal01.json"; +const proposal02AuthFile = ".auth/proposal02.json"; setup.beforeEach(async () => { await setAllureEpic("Setup"); @@ -140,8 +142,26 @@ setup("Create Proposal 01 auth", async ({ page, context }) => { await proposalDiscussionPage.verifyIdentityBtn.click(); await proposalDiscussionPage.setUsername( - faker.internet.userName().toLowerCase() + faker.internet.userName().toLowerCase() ); await context.storageState({ path: proposal01AuthFile }); }); + +setup("Create Proposal 02 auth", async ({ page, context }) => { + await importWallet(page, proposal02Wallet); + + const loginPage = new LoginPage(page); + await loginPage.login(); + await loginPage.isLoggedIn(); + + const proposalDiscussionPage = new ProposalDiscussionPage(page); + await proposalDiscussionPage.goto(); + await proposalDiscussionPage.verifyIdentityBtn.click(); + + await proposalDiscussionPage.setUsername( + faker.internet.userName().toLowerCase() + ); + + await context.storageState({ path: proposal02AuthFile }); +}); diff --git a/tests/govtool-frontend/playwright/tests/proposal.setup.ts b/tests/govtool-frontend/playwright/tests/governance-action.setup.ts similarity index 100% rename from tests/govtool-frontend/playwright/tests/proposal.setup.ts rename to tests/govtool-frontend/playwright/tests/governance-action.setup.ts