Skip to content

Commit

Permalink
playwright integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Remus287 committed Dec 16, 2024
1 parent 71c2435 commit ba12d54
Show file tree
Hide file tree
Showing 8 changed files with 388 additions and 1 deletion.
78 changes: 78 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,10 @@
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@mui/material": "^5.16.1"
}
},
"devDependencies": {
"@playwright/test": "^1.49.0",
"@types/node": "^22.10.1"
},
"scripts": {}
}
27 changes: 27 additions & 0 deletions playwright.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { defineConfig, devices } = require('@playwright/test');


module.exports = defineConfig({
testDir: './tests',
workers: 2,
retries: 1,
use: {
trace: 'retain-on-failure',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},

{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},

{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
]
});
107 changes: 107 additions & 0 deletions tests/candidateInfo.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
const { test, expect } = require('@playwright/test');

const url = 'http://localhost:3000/';


test.beforeEach(async ({ page }) => {
await page.goto(url);

// navigate to candidate info page
const navButton = page.getByRole('banner').getByRole('button', { name: 'Candidate Info' });
await navButton.click();
await page.waitForURL(url + 'candidateInfo');
});

test ('Candidate More Info', async ({ page }) => {
// Get all candidates
await page.waitForSelector('.candidate-card');
const candidateList = await page.locator('.candidate-card').all();
for (const candidate of candidateList) {
const candidateName = await candidate.getByRole('heading').innerText();
await candidate.getByRole('button').click();
await expect.soft(page.getByRole('heading').first()).toHaveText(candidateName);
await page.goBack();
}
});

// list of all permutations of filters
const filterList = (function() {
const politicalAffliiation = [null, 'Democrat', 'Republican', 'Independent', 'Non Partisan'];
const electionType = [null, 'Federal Election', 'State Election', 'Municipal Election', 'Special Election', 'Primary Election', 'Ballot Questions/Referendum'];
const district = [null, 'District 1', 'District 2', 'District 3', 'District 4'];
const list = [];
for (const party of politicalAffliiation) {
for (const election of electionType) {
for (const dist of district) {
const filter = {
party: party,
election: election,
district: dist
}
list.push(filter);
}
}
}
return list;
})();

const exampleFiltersList = [
{ party: 'Democrat', election: null, district: null },
{ party: 'Republican', election: null, district: null }
]

exampleFiltersList.forEach((filter) => {
test (`Filter ${filter.party} ${filter.election} ${filter.district} Candidates`, async ({ page }) => {
// Get all candidate info
await page.waitForSelector('.candidate-card');
const candidateList = await page.locator('.candidate-card').all();
var candidateInfoList = [];
for (const candidate of candidateList) {
const candidateName = await candidate.getByRole('heading').innerText();
const candidateParty = await candidate.locator('p').filter({ hasText: 'Party' }).innerText();
const candidateOffice = await candidate.locator('p').filter({ hasText: 'Office' }).innerText();
const candidateDistrict = await candidate.locator('p').filter({ hasText: 'District' }).innerText();
const candidateElection = await candidate.locator('p').filter({ hasText: 'Election' }).innerText();
const candidateInfo = {
name: candidateName,
party: candidateParty.replace('Party: ', ''),
office: candidateOffice.replace('Office: ', ''),
district: candidateDistrict.replace('District: ', ''),
election: candidateElection.replace('Election: ', '')
}
candidateInfoList.push(candidateInfo);
}

// Enter filter values

if (filter.party != null) {
const politicalAffiliation = page.getByLabel('Political Affiliation');
await politicalAffiliation.selectOption({ value: filter.party })
};
if (filter.election != null) {
const electionType = page.getByLabel('Election Type');
await electionType.selectOption({ value: filter.election });
}
if (filter.district != null) {
const district = page.getByLabel('District');
await district.selectOption({ value: filter.district });
}

// Filter candidates
const filteredCandidateInfoList = candidateInfoList.filter(candidate =>
(filter.party != null ? candidate.party === filter.party : true) &&
(filter.election != null ? candidate.election === filter.election : true) &&
(filter.district != null ? candidate.district === filter.district : true)
);

// Check that the filtered candidates match the displayed candidates
await expect(page.locator('.candidate-card')).toHaveCount(filteredCandidateInfoList.length);
const filteredCandidateList = await page.locator('.candidate-card').all();
for (const candidate of filteredCandidateList){
const candidateName = await candidate.getByRole('heading').innerText();
const isCandidateInList = filteredCandidateInfoList.some(filteredCandidate => filteredCandidate.name === candidateName);
await expect(isCandidateInList).toBe(true);
}
});
});

35 changes: 35 additions & 0 deletions tests/dropBoxLocations.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const { test, expect } = require('@playwright/test');
const url = 'http://localhost:3000/';

test.beforeEach(async ({ page }) => {
await page.goto(url);

// Navigate to the drop box locations page
const navButton = page.getByRole('banner').getByRole('button', { name: 'Drop Box Locations' });
await navButton.click();
await page.waitForURL(url + 'dropBoxLocations');
});

test('Early Voting Locations Link', async ({ page }) => {
// check button link
const linkPromise = page.waitForEvent("popup");
await page.getByRole('button', { name: 'Early Voting Locations' }).click();
const linkTab = await linkPromise;
await expect(linkTab).toHaveURL('https://www.boston.gov/departments/elections/early-voting-boston#map--737516');
});


[
{ input: '700 Commonwealth Ave', expected: '700 Commonwealth Avenue, Boston, Massachusetts, 02215' },
{ input: 'Boston City Hall', expected: 'Boston City Hall' },
{ input: 'Boston Public Library', expected: 'Boston Public Library' },
].forEach((address) => {
test(`Find Address or Place: ${address.input}`, async ({ page }) => {
const iframe = await page.locator('iframe').contentFrame();
const addressInput = await iframe.getByPlaceholder('Find address or place');
await addressInput.fill(address.input);
await iframe.getByRole('button', { name: 'Search', exact: true }).click();
await expect(iframe.locator('article.container')).toBeVisible();
await expect(iframe.locator('.esri-search-result-renderer__more-results-item').filter({ hasNotText: 'Show more results'})).toHaveText(address.expected);
});
});
29 changes: 29 additions & 0 deletions tests/upcomingElections.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const { test, expect } = require('@playwright/test');

const url = 'http://localhost:3000/';

test.beforeEach(async ({ page }) => {
await page.goto(url);
});


[
{ electionType: 'State Election', dateType: 'Registration Deadline' },
{ electionType: 'State Election', dateType: 'Election Day' },
{ electionType: 'General Election', dateType: 'Registration Deadline' },
{ electionType: 'General Election', dateType: 'Election Day' },
{ electionType: 'Governors Council', dateType: 'Registration Deadline' },
{ electionType: 'Governors Council', dateType: 'Election Day' }
].forEach(({ electionType, dateType }) => {
test(`Add ${electionType} ${dateType} to Google Calendar`, async ({ page }) => {
await page.waitForSelector('.event-card');
const stateElectionCard = page.locator('.event-card').filter({ hasText: electionType });
const stateElectionDate = await stateElectionCard.locator('>div>div').filter({ hasText: dateType });

const googleCalendarPromise = page.waitForEvent("popup");
await stateElectionDate.getByRole('button').click();
const googleCalendarTab = await googleCalendarPromise;
await expect(googleCalendarTab).toHaveURL("https://workspace.google.com/intl/en-US/products/calendar/");
await googleCalendarTab.close();
});
});
61 changes: 61 additions & 0 deletions tests/voterInfo.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const { test, expect } = require('@playwright/test');
const url = 'http://localhost:3000/';

[
{
street: '700 Commonwealth Ave',
city: 'Boston',
zip: '02215',
ward: '21',
precinct: '2',
},
// Boston Public Market
{
street: '100 Hanover St',
city: 'Boston',
zip: '02108',
ward: '3',
precinct: '6',
},
// Boston College
{
street: '140 Commonwealth Ave',
city: '',
zip: '02467',
ward: '21',
precinct: '16',
}
].forEach((address) => {
test(`Get Ballot Info From Address ${address.street}`, async ({ page }) => {
await page.goto(url);

// navigate to voter info page
const navButton = page.getByRole('banner').getByRole('button', { name: 'Your Voter Info' });
await navButton.click();
await page.waitForURL(url + 'voterInfo');

// Check page heading
await page.isVisible('text=Your Voter Info');

// fill in address info
const streetInput = page.getByLabel('Street');
await streetInput.fill(address.street);
const cityInput = page.getByLabel('City');
await cityInput.fill(address.city);
const zipInput = page.getByLabel('Zip');
await zipInput.fill(address.zip);

// submit address
await page.getByRole('button', { name: 'Submit Address' }).click();

// check ballot info
await expect(page.getByText(`Your Ward: ${address.ward}`)).toBeVisible();
await expect(page.getByText(`Your Precinct: ${address.precinct}`)).toBeVisible();

// check ballot link
const ballotPromise = page.waitForEvent("popup");
await page.getByRole('link', { name: 'View Your Ballot' }).click();
const ballotTab = await ballotPromise;
await expect(ballotTab).toHaveURL(`https://www.sec.state.ma.us/WhereDoIVoteMA/ShowBallot/ViewMyBallot/BallotOut/ST/35/${address.ward}/${address.precinct}`);
});
});
Loading

0 comments on commit ba12d54

Please sign in to comment.