Skip to content

Commit

Permalink
Test: Implement 1-2A Update user profile
Browse files Browse the repository at this point in the history
A CO can update individual fields in the information held on a given user of the CVT
  • Loading branch information
Sital999 committed Nov 17, 2024
1 parent 464bd3c commit 89e128c
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 78 deletions.
2 changes: 1 addition & 1 deletion integration_test/lib/fixtures/poll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export const test = base.extend<TestOptions & { pollId: number }>({
await userPollPage.goto(pollId);
// cast vote
await userPage.getByTestId(votes[index]).click();
await userPage.getByText('Vote recorded').isVisible()
await userPage.getByText('Vote recorded').isVisible();
await userPage.close();
}
)
Expand Down
66 changes: 42 additions & 24 deletions integration_test/lib/pages/representativesPage.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { Page, expect } from '@playwright/test';
import { faker } from '@faker-js/faker';

const updateDelegateEmail = faker.person.fullName + '@email.com';
const updatedAlternateEmail = faker.person.fullName + '@email.com';
const representativeUpdatedToast = 'User info updated!';
export default class RepresentativesPage {
readonly updateDelegateBtn = this.page.getByTestId(
Expand Down Expand Up @@ -30,26 +27,40 @@ export default class RepresentativesPage {
await this.page.goto('/representatives/manage');
}

async updateDelegateProfile(): Promise<void> {
async updateUserProfile(
name: string,
email: string,
stake_address: string
): Promise<void> {
// await this.goto();
// await this.page
// .locator('[data-testid^="edit-representative-info-"]')
// .first()
// .click();
// await this.page.getByRole('textbox').nth(0).fill(name);
// await this.page.getByRole('textbox').nth(1).fill(email);
// await this.page
// .locator('[data-testid^="save-representative-info-"]')
// .first()
// .click();
await this.goto();
await this.updateDelegateBtn.click();
await this.page.getByRole('textbox').nth(1).fill(updateDelegateEmail);
await this.page.getByRole('textbox').nth(0).fill(name);
await this.page.getByRole('textbox').nth(1).fill(email);
await this.page.getByRole('textbox').nth(2).fill(stake_address);
await this.saveDelegateInfoBtn.click({ force: true });
}

async isRepresentativeUpdated(): Promise<void> {
async isRepresentativeUpdated(infos: Array<string>): Promise<void> {
await expect(this.page.getByText(representativeUpdatedToast)).toBeVisible();
}

async updateAlternateProfile(): Promise<void> {
await this.goto();
await this.updateAlternateBtn.click();
await this.page.getByRole('textbox').nth(1).fill(updatedAlternateEmail);
await this.saveAlternateBtn.click({ force: true });
await Promise.all(
infos.map(
async (info) => await expect(this.page.getByText(info)).toBeVisible()
)
);
}

async switchVotingPower(): Promise<void> {
await this.goto();
await this.transferVotingPowerBtn.click();
const currentActiveVoter = await this.page
.getByRole('combobox')
Expand All @@ -70,18 +81,25 @@ export default class RepresentativesPage {
.locator('[data-id="1"]')
.locator('[data-field="active_voter_id"]')
.innerText();
const changedRow = await this.page
await this.page
.locator('[data-id="1"]')
.filter({ has: this.page.getByTestId('edit-active-voter-1') })
.allInnerTexts();
const changedRowData = changedRow[0].split('\n\n');
const activeVoter =
activeVoterRole === 'Delegate' ? changedRowData[1] : changedRowData[2];
await this.page.goto('/');
const activeVoterNamme = await this.page
.locator(`[data-testid^="${activeVoterRole.toLowerCase()}-name-"]`)
.click({ force: true });
await expect(this.page.locator('.MuiChip-root').first()).toHaveText(
'Active Voter'
);
}

async getRepresentativeId(isDelegate: boolean = false): Promise<string> {
await expect(this.page.getByRole('row').first()).toBeVisible();
const representativeTestId = await this.page
.locator('[data-id="1"]')
.locator('[data-field="active_voter"]')
.innerText();
expect(activeVoterNamme).toBe(activeVoter);
.filter({ has: this.page.getByTestId('edit-active-voter-1') })
.locator(
`[data-testid^="${isDelegate ? 'delegate' : 'alternate'}-name-"]`
)
.getAttribute('data-testid');
return representativeTestId.split('-').pop();
}
}
49 changes: 25 additions & 24 deletions integration_test/tests/0-common/comon.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ test.describe('Polls', () => {
test.describe('Polls', () => {
test.use({
pollType: 'VotedPoll',
});
});

/**
* Description: After a poll is closed the results of the poll should be displayed*
Expand Down Expand Up @@ -98,13 +98,12 @@ test.describe('Polls', () => {
await expect(noCount).toHaveText('1');
await expect(abstainCount).toHaveText('1');
});

});

test.describe('User profile', () => {
test.use({
pollType: 'VotedPoll',
});
});

/**
* Description: By going to the profile page of a delegate or alternate I can review their voting record
Expand All @@ -118,25 +117,28 @@ test.describe('User profile', () => {
test('0-2A-1. Given Delegate or alternate profile page, can view voting hsitory', async ({
page,
pollId,
browser
browser,
}) => {
await page.goto('/polls/'+pollId);

await page.goto('/polls/' + pollId);

const buttons = await page.locator('[data-testid^="representative-vote-"]').all();
const buttons = await page
.locator('[data-testid^="representative-vote-"]')
.all();

if (buttons.length === 0) {
throw new Error('No representative vote buttons found');
}
const pages:Page[]=[];
const pages: Page[] = [];
for (const button of buttons) {
const testId = await button.getAttribute('data-testid');
console.log(`Opening new tab for button with test id: ${testId}`);

// Get the href attribute or construct the URL for navigation
const href = await button.getAttribute('href');
if (!href) {
throw new Error(`Button with test id: ${testId} does not have an href attribute`);
throw new Error(
`Button with test id: ${testId} does not have an href attribute`
);
}

// Open a new tab
Expand All @@ -146,14 +148,14 @@ test.describe('User profile', () => {

pages.push(newPage);
}
await Promise.all(pages.map(async (voterPage)=>{
const votingTable= voterPage.getByTestId('voting-history-table');
await votingTable.getByTestId('user-votes-'+pollId).isVisible();
}));

await Promise.all(
pages.map(async (voterPage) => {
const votingTable = voterPage.getByTestId('voting-history-table');
await votingTable.getByTestId('user-votes-' + pollId).isVisible();
})
);
});


/**
* Description: By going to the profile page of a delegate or alternate I can review their voting record
*
Expand All @@ -167,28 +169,27 @@ test.describe('User profile', () => {
test('0-2A-1. Can navigate to user profile from delegate/alternate listing page', async ({
page,
}) => {

throw new Error('Not Implemented');
});


test('0-2A-1. Can navigate to user profile from voter view in poll results page', async ({
page,
pollId,
}) => {
await page.goto('polls/' + pollId);

// Locate the buttons
const buttons = await page.locator('[data-testid^="representative-vote-"]').all();

const buttons = await page
.locator('[data-testid^="representative-vote-"]')
.all();

if (buttons.length === 0) {
throw new Error('No representative vote buttons found');
}

// Click the first button
await buttons[0].click();

await page.waitForURL(/\/representatives\/\d+$/);

await page.waitForURL(/\/representatives\/\d+$/);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ test.describe('Delete Poll', async () => {
await homePage.deleteOpenPollCards();
pollId = await homePage.createPoll();
});

test('1-1F-1. Given connected as CO, can delete a pending poll', async ({
page,
}) => {
Expand Down Expand Up @@ -204,6 +205,8 @@ test.describe('Create Poll', () => {
});

test.describe('User Control', () => {
test.use({ pollType: 'CreatePoll' });

/**
* Description: A CO can update individual fields in the information held on a given user of the CVT
*
Expand All @@ -214,29 +217,21 @@ test.describe('User Control', () => {
*/
test('1-2A. Given connected as CO can update all fields of user', async ({
page,
browser,
}) => {
throw new Error('Not Implemented');
});

/**
* Description: If a delegate is unable to vote then their alternate needs to be given voting rights, and if they become able to vote again, then the voting rights need to be able to be returned.
*
* User Story: As a CO, I want to be able to choose either the delegate or the alternate from any given workshop to have the right to vote on behalf of the workshop participants so that every workshop has the opportunity to cast exactly one vote in each poll
*
* Acceptance Criteria: Given that I am a CO on the page listing all the delegates and alternates, when I toggle one of them to be the voter from a given workshop that one can vote, the other one from the workshop is not able to vote.
*/
test('1-2B-1. Given connected as CO can switch delegate user to alternate or vice-versa', async ({
page,
pollId,
}) => {
const representativePage = new RepresentativesPage(page);
await representativePage.switchVotingPower();
await expect(page.getByText('Active voter updated!')).toBeVisible();
// TODO: go to listing page and confirm that the role is change.
// again switch and test.
const name = faker.person.fullName();
const email = name.split(' ')[0] + '@email.com';
const stake_address = faker.person.jobArea();
const represntativePage = new RepresentativesPage(page);
await represntativePage.updateUserProfile(name, email, stake_address);
await represntativePage.isRepresentativeUpdated([
name,
email,
stake_address,
]);
});

test('1-2B-2. Should have corresponding workspace delegate and alternate in a same row', async ({
test('1-2B. Should have corresponding workspace delegate and alternate in a same row', async ({
page,
}) => {
await page.goto('/');
Expand Down Expand Up @@ -271,26 +266,78 @@ test.describe('User Control', () => {
)
);
});
// As a convention organiser, I want to be able to update the profile information of a delegate (or alternate) to correct any error or omission.
test('1-2D. Convention organisers can update delegate profile information ', async ({

test('1-2D. Should not be able to switch active voting power between delegate and alternate during voting', async ({
page,
pollId,
}) => {
const represntativePage = new RepresentativesPage(page);
await represntativePage.updateDelegateProfile();
await represntativePage.isRepresentativeUpdated();
await represntativePage.updateAlternateProfile();
await represntativePage.isRepresentativeUpdated();
test.slow();
const pollPage = new PollPage(page);
await pollPage.goto(pollId);
await pollPage.beginVoteBtn.click();

// before switching power while poll is opened for voting
const representativePage = new RepresentativesPage(page);
await representativePage.goto();
await expect(page.getByRole('row').first()).toBeVisible();
const previousActiveVoterId = await page
.locator('[data-id="1"]')
.locator('[data-field="active_voter_cell"]')
.getAttribute('data-testid');

await representativePage.switchVotingPower();
await page.waitForTimeout(500);

// // after trying to switch power while poll is opened for voting
await expect(page.getByRole('status')).toHaveText(
'You cannot change the active voter while a Poll is actively voting.'
);
const currentActiveVoterId = await page
.locator('[data-id="1"]')
.locator('[data-field="active_voter_cell"]')
.getAttribute('data-testid');

expect(previousActiveVoterId).toBe(currentActiveVoterId);
});
});

/**
* Description: If a delegate is unable to vote then their alternate needs to be given voting rights, and if they become able to vote again, then the voting rights need to be able to be returned.
*
* User Story: As a CO, I want to be able to choose either the delegate or the alternate from any given workshop to have the right to vote on behalf of the workshop participants so that every workshop has the opportunity to cast exactly one vote in each poll
*
* Acceptance Criteria: Given that I am a CO on the page listing all the delegates and alternates, when I toggle one of them to be the voter from a given workshop that one can vote, the other one from the workshop is not able to vote.
*/

test.describe('Voting Power', () => {
test.beforeEach(async ({ page }) => {
const homePage = new HomePage(page);
await homePage.goto();
await homePage.deleteOpenPollCards();
});
test('1-3A. Should be able to switch active voting power between delegate and alternate.', async ({
page,
}) => {
const representativePage = new RepresentativesPage(page);
await representativePage.goto();
const previousActiveVoterId = await page
.locator('[data-id="1"]')
.locator('[data-field="active_voter_cell"]')
.getAttribute('data-testid');
await representativePage.switchVotingPower();

await expect(page.getByText('Active voter updated!')).toBeVisible();
await representativePage.assertSwitchedVotingPower();
await representativePage.switchVotingPower();
const representativesIds = await Promise.all([
representativePage.getRepresentativeId(true),
representativePage.getRepresentativeId(),
]);
const currentActiveVoterId = await page
.locator('[data-id="1"]')
.locator('[data-field="active_voter_cell"]')
.getAttribute('data-testid');

expect(representativesIds).toContain(previousActiveVoterId);
expect(representativesIds).toContain(currentActiveVoterId);
expect(currentActiveVoterId).not.toBe(previousActiveVoterId);
});
});
2 changes: 2 additions & 0 deletions src/components/coordinator/manageActivePowerTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ export function ManageActivePowerTable(): JSX.Element {
flexDirection="row"
alignItems="center"
height="100%"
data-testid={`${activeVoterId}`}
data-field="active_voter_cell"
>
<Typography>
{activeVoterId == delegateId
Expand Down

0 comments on commit 89e128c

Please sign in to comment.