integration/pages/RosterTestPage.js (134 lines of code) (raw):
const BaseTestPage = require('./BaseTestPage');
const assert = require('assert');
const { By } = require('selenium-webdriver');
const ELEMENTS = {
toggleMicrophoneButton: By.css(
'[data-testid=\'button\'][label=\'Mute\'], [data-testid=\'button\'][label=\'Unmute\']'
),
toggleVideoButton: By.css('[data-testid=\'button\'][label=\'Video\']'),
toggleSpeakerButton: By.css('[data-testid=\'button\'][label=\'Speaker\']'),
toggleContentButton: By.css('[data-testid=\'button\'][label=\'Content\']'),
roster: By.css('.roster'),
rosterCell: By.css('[data-testid=\'roster-cell\']'),
hookStates: By.css('pre'),
attendeeState: By.css('code'),
};
class RosterTestPage extends BaseTestPage {
constructor(driver) {
super(driver);
}
async getRosterLength() {
const rosterCells = await this.findAll(ELEMENTS.rosterCell);
return rosterCells.length;
}
async getAttendeeRosterCell(attendeeName) {
const rosterCells = await this.findAll(ELEMENTS.rosterCell);
for (const rosterCell of rosterCells) {
const name = await rosterCell.getText();
if (name === attendeeName) {
return rosterCell;
}
}
}
async getAttendeeStates(attendeeName) {
const hookStates = this.find(ELEMENTS.hookStates);
const attendeeStates = await hookStates.findElements(ELEMENTS.attendeeState);
for (const attendeeState of attendeeStates) {
const testId = await attendeeState.getAttribute('data-testid');
if (testId === ('code-' + attendeeName)) {
return JSON.parse(await attendeeState.getText());
}
}
return {};
}
async getAttendeeState(attendeeName, property) {
const attendeeState = await this.getAttendeeStates(attendeeName);
const hookState = Object.values(attendeeState)[0];
return hookState[property];
}
async getLengthOfAttendeeStates() {
const hookStates = this.find(ELEMENTS.hookStates);
const attendeeStates = await hookStates.findElements(ELEMENTS.attendeeState);
return attendeeStates.length;
}
async checkRosterLength(targetLength) {
const isMatched = await this.waitUntil(async () => {
const actualLength = await this.getRosterLength();
return actualLength === targetLength;
});
assert(isMatched, `The length of roster is not ${targetLength}`);
}
async checkIfAttendeeIsInRoster(attendeeName) {
const isMatched = this.waitUntil(async () => {
const rosterCells = await this.findAll(ELEMENTS.rosterCell);
for (const rosterCell of rosterCells) {
const name = await rosterCell.getText();
return name === attendeeName;
}
});
assert(isMatched, `Attendee ${attendeeName} is not in the roster`);
}
async checkLengthOfAttendeeStates(targetLength) {
const length = await this.getLengthOfAttendeeStates();
assert(length === targetLength, `The length of attendee states is not ${targetLength} but ${length}`);
}
async checkAttendeeState(attendeeName, property, value, equal = true) {
const passed = await this.waitUntil(async () => {
const state = await this.getAttendeeState(attendeeName, property);
if (equal) {
return state === value;
} else {
return state !== value;
}
});
assert(passed, `Wrong attendee property, the ${property} of ${attendeeName} should be ${value}`);
}
async toggleMicrophone() {
await this.find(ELEMENTS.toggleMicrophoneButton).click();
}
async toggleVideo() {
await this.find(ELEMENTS.toggleVideoButton).click();
}
async toggleSpeaker() {
await this.find(ELEMENTS.toggleSpeakerButton).click();
}
async toggleContent() {
await this.find(ELEMENTS.toggleContentButton).click();
}
async checkMicrophoneIcon(attendeeName, muted) {
const isMatched = await this.waitUntil(async () => {
const rosterCell = await this.getAttendeeRosterCell(attendeeName);
const title = await rosterCell.findElement(By.css('title')).getAttribute('innerHTML');
const target = muted ? 'Muted microphone' : 'Microphone';
return title === target;
});
assert(isMatched, `Wrong microphone icon when muted is ${muted}`);
}
async checkVideoIcon(attendeeName, videoEnabled) {
const isMatched = await this.waitUntil(async () => {
const rosterCell = await this.getAttendeeRosterCell(attendeeName);
const childElements = await rosterCell.findElements(By.xpath('*'));
const videoIcon = childElements[2];
// Compare the path definition value of the video icon SVG to determine if it is the target icon.
// When video is enabled, it should start with 'M19', otherwise it should start with 'M4'.
const d = await videoIcon.findElement(By.css('path')).getAttribute('d');
return videoEnabled === d.startsWith('M19');
});
assert(isMatched, `Wrong video icon when videoEnabled is ${videoEnabled}`);
}
async checkContentIcon(attendeeName, sharingContent) {
const isMatched = await this.waitUntil(async () => {
const rosterCell = await this.getAttendeeRosterCell(attendeeName);
const childElements = await rosterCell.findElements(By.xpath('*'));
const contentIcon = childElements[2];
let title;
try {
title = await contentIcon.findElement(By.css('title'))?.getAttribute('innerHTML');
} catch (error) {
title = '';
}
const target = sharingContent ? 'Screen share' : '';
return title === target;
});
assert(isMatched, `Wrong content icon when sharingContent is ${sharingContent}`);
}
}
module.exports = RosterTestPage;