Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update and add Polling specs #11574

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 7 additions & 2 deletions bigbluebutton-html5/imports/ui/components/poll/component.jsx
Expand Up @@ -325,6 +325,7 @@ class Poll extends Component {
type="text"
value={o.val}
placeholder={intl.formatMessage(intlMessages.customPlaceholder)}
data-test="pollOptionItem"
className={styles.pollOption}
onChange={e => this.handleInputChange(e, i)}
maxLength={MAX_INPUT_CHARS}
Expand All @@ -334,6 +335,7 @@ class Poll extends Component {
className={styles.deleteBtn}
label={intl.formatMessage(intlMessages.delete)}
icon="delete"
data-test="deletePollOption"
hideLabel
circle
color="default"
Expand Down Expand Up @@ -394,6 +396,7 @@ class Poll extends Component {
<div>
<h4>{intl.formatMessage(intlMessages.questionTitle)}</h4>
<textarea
data-test="pollQuestionArea"
className={styles.pollQuestion}
value={question}
onChange={e => this.handleTextareaChange(e)}
Expand All @@ -407,7 +410,7 @@ class Poll extends Component {
<div className={styles.errorSpacer}>&nbsp;</div>
)}
</div>
<div>
<div data-test="responseTypes">
<h4>{intl.formatMessage(intlMessages.responseTypesLabel)}</h4>
<div className={styles.responseType}>
<Button
Expand Down Expand Up @@ -465,7 +468,7 @@ class Poll extends Component {
</div>
{ type
&& (
<div>
<div data-test="responseChoices">
<h4>{intl.formatMessage(intlMessages.responseChoices)}</h4>
{
type === 'RP'
Expand Down Expand Up @@ -494,6 +497,7 @@ class Poll extends Component {
&& (
<Button
className={styles.addItemBtn}
data-test="addItem"
label={intl.formatMessage(intlMessages.addOptionLabel)}
color="default"
icon="add"
Expand All @@ -504,6 +508,7 @@ class Poll extends Component {
}
<Button
className={styles.startPollBtn}
data-test="startPoll"
label={intl.formatMessage(intlMessages.startPollLabel)}
color="primary"
onClick={() => {
Expand Down
Expand Up @@ -80,7 +80,7 @@ class LiveResult extends PureComponent {
(
<tr key={_.uniqueId('stats-')}>
<td className={styles.resultLeft}>{user.name}</td>
<td className={styles.resultRight}>
<td data-test="receivedAnswer" className={styles.resultRight}>
{
pollAnswerIds[formattedMessageIndex]
? intl.formatMessage(pollAnswerIds[formattedMessageIndex])
Expand Down
Expand Up @@ -4,9 +4,9 @@ import Button from '/imports/ui/components/button/component';
import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
import { defineMessages, injectIntl } from 'react-intl';
import cx from 'classnames';
import { Meteor } from 'meteor/meteor';
import { styles } from './styles.scss';
import AudioService from '/imports/ui/components/audio/service';
import {Meteor} from "meteor/meteor";

const MAX_INPUT_CHARS = 45;

Expand Down Expand Up @@ -111,6 +111,7 @@ class Polling extends Component {
return (
<div className={styles.overlay}>
<div
data-test="pollingContainer"
className={cx({
[styles.pollingContainer]: true,
[styles.autoWidth]: stackOptions,
Expand All @@ -120,7 +121,7 @@ class Polling extends Component {
{question.length > 0 && (
<span className={styles.qHeader}>
<div className={styles.qTitle}>{intl.formatMessage(intlMessages.pollQestionTitle)}</div>
<div className={styles.qText}>{question}</div>
<div data-test="pollQuestion" className={styles.qText}>{question}</div>
</span>)
}
{ poll.pollType !== 'RP' && (
Expand Down Expand Up @@ -156,6 +157,7 @@ class Polling extends Component {
onClick={() => handleVote(poll.pollId, pollAnswer)}
aria-labelledby={`pollAnswerLabel${pollAnswer.key}`}
aria-describedby={`pollAnswerDesc${pollAnswer.key}`}
data-test="pollAnswerOption"
/>
<div
className={styles.hidden}
Expand All @@ -180,6 +182,7 @@ class Polling extends Component {
&& (
<div className={styles.typedResponseWrapper}>
<input
data-test="pollAnswerOption"
onChange={(e) => {
this.handleUpdateResponseInput(e);
}}
Expand All @@ -193,6 +196,7 @@ class Polling extends Component {
ref={(r) => { this.responseInput = r; }}
/>
<Button
data-test="submitAnswer"
className={styles.submitVoteBtn}
disabled={typedAns.length === 0}
color="primary"
Expand Down
21 changes: 21 additions & 0 deletions bigbluebutton-html5/tests/puppeteer/core/page.js
Expand Up @@ -292,12 +292,33 @@ class Page {
}
}

// Press a keyboard button
async press(key) {
await this.page.keyboard.press(key);
}

// Press and hold a keyboard button
async hold(key) {
await this.page.keyboard.down(key);
}

// Release a hold pressed keyboard button
async release(key) {
await this.page.keyboard.up(key);
}

async click(element, relief = false) {
if (relief) await helper.sleep(1000);
await this.waitForSelector(element, ELEMENT_WAIT_TIME);
await this.page.click(element, true);
}

async clickNItem(element, relief = false, n) {
if (relief) await helper.sleep(1000);
const elementHandle = await this.page.$$(element);
await elementHandle[n].click();
}

async type(element, text, relief = false) {
if (relief) await helper.sleep(1000);
await this.waitForSelector(element, ELEMENT_WAIT_TIME);
Expand Down
30 changes: 30 additions & 0 deletions bigbluebutton-html5/tests/puppeteer/polling.obj.js
@@ -1,4 +1,5 @@
const CustomParameters = require('./customparameters/customparameters');
const Multiusers = require('./user/multiusers');
const Polling = require('./polling/poll');
const Page = require('./core/page');
const Poll = require('./chat/poll');
Expand Down Expand Up @@ -97,5 +98,34 @@ const pollingTest = () => {
});
}
});

// This Test chooses randomly a polling case, runs it
// and expects having it answered by the other user
test('Random Poll', async () => {
const test = new Multiusers();
let response;
let screenshot;
try {
const testName = 'randomPoll';
await test.page1.logger('begin of ', testName);
await test.init(undefined, testName);
response = await test.randomPoll(testName);
await test.page1.logger('end of ', testName);
await test.page1.stopRecording();
await test.page2.stopRecording();
screenshot = await test.page1.page.screenshot();
} catch (e) {
await test.page1.logger(e);
} finally {
await test.close(test.page1, test.page2);
}
expect(response).toBe(true);
if (process.env.REGRESSION_TESTING === 'true') {
expect(screenshot).toMatchImageSnapshot({
failureThreshold: 0.5,
failureThresholdType: 'percent',
});
}
});
};
module.exports = exports = pollingTest;
16 changes: 15 additions & 1 deletion bigbluebutton-html5/tests/puppeteer/polling/elemens.js
@@ -1 +1,15 @@
exports.pollingContainer = 'div[class^="pollingContainer"]';
exports.pollingContainer = 'div[data-test="pollingContainer"]';
exports.pollQuestionArea = 'textarea[data-test="pollQuestionArea"]';
exports.pollQuestion = 'Are we good ?';
exports.responseTypes = 'div[data-test="responseTypesLabel"]';
exports.responseChoices = 'div[data-test="responseChoices"]';
exports.addItem = 'button[data-test="addItem"]';
exports.pollOptionItem = 'input[data-test="pollOptionItem"]';
exports.uncertain = 'Uncertain';
exports.deletePollOption = 'button[data-test="deletePollOption"]';
exports.pollAnswerOptionBtn = 'button[data-test="pollAnswerOption"]';
exports.pollAnswerOptionInput = 'input[data-test="pollAnswerOption"]';
exports.pollSubmitAnswer = 'button[data-test="submitAnswer"]';
exports.startPoll = 'button[data-test="startPoll"]';
exports.receivedAnswer = 'td[data-test="receivedAnswer"]';
exports.publishLabel = 'button[data-test="publishLabel"]';
102 changes: 102 additions & 0 deletions bigbluebutton-html5/tests/puppeteer/user/multiusers.js
@@ -1,6 +1,12 @@
const Page = require('../core/page');
const params = require('../params');
const util = require('../chat/util');
const utilCustomParams = require('../customparameters/util');
const pe = require('../core/elements');
const ne = require('../notifications/elements');
const ple = require('../polling/elemens');
const { ELEMENT_WAIT_TIME, ELEMENT_WAIT_LONGER_TIME } = require('../core/constants');
const { sleep } = require('../core/helper');

class MultiUsers {
constructor() {
Expand Down Expand Up @@ -45,6 +51,102 @@ class MultiUsers {
return checks.firstCheck !== false && checks.secondCheck !== false;
}

async randomPoll(testName) {
try {
await this.page1.startRecording(testName);
await this.page1.closeAudioModal();
await this.page2.startRecording(testName);
await this.page2.closeAudioModal();
await this.page1.waitForSelector(pe.actions, ELEMENT_WAIT_TIME);
await this.page1.click(pe.actions, true);
await this.page1.waitForSelector(ne.polling, ELEMENT_WAIT_TIME);
await this.page1.click(ne.polling, true);
await this.page1.waitForSelector(ple.pollQuestionArea, ELEMENT_WAIT_TIME);
await this.page1.page.focus(ple.pollQuestionArea);
await this.page1.page.keyboard.type(ple.pollQuestion);

const chosenRandomNb = await this.page1.page.evaluate(() => {
const responseTypesDiv = document.querySelector('div[data-test="responseTypes"]');
const buttons = responseTypesDiv.querySelectorAll('button');
const countButtons = buttons.length;
const randomNb = Math.floor(Math.random() * countButtons) + 1;
const chosenRandomNb = randomNb - 1;
responseTypesDiv.querySelectorAll('button')[chosenRandomNb].click();
return chosenRandomNb;
});

const customs = {
0: ple.uncertain,
1: 0,
2: 'ABSTENTION',
3: 'All good!',
};
switch (chosenRandomNb) {
case 0:
// Adding a poll option
console.log({ chosenRandomNb }, ' <= True / False');
await this.page1.waitForSelector(ple.responseChoices, ELEMENT_WAIT_TIME);
await this.page1.waitForSelector(ple.addItem, ELEMENT_WAIT_TIME);
await this.page1.click(ple.addItem, true);
await this.page1.click(ple.pollOptionItem, true);
await this.page1.tab(2);
await this.page1.page.keyboard.type(customs[0]);
break;

case 1:
// Deleting a poll option
console.log({ chosenRandomNb }, ' <= A / B / C / D');
await this.page1.waitForSelector(ple.deletePollOption, ELEMENT_WAIT_TIME);
await this.page1.clickNItem(ple.deletePollOption, true, customs[1]);
break;

case 2:
// Editing a poll option
console.log({ chosenRandomNb }, ' <= Yes / No / Abstention');
await this.page1.waitForSelector(ple.responseChoices, ELEMENT_WAIT_TIME);
await this.page1.clickNItem(ple.pollOptionItem, true, 2);
await this.page1.hold('Control');
await this.page1.press('KeyA');
await this.page1.release('Control');
await this.page1.page.keyboard.type(customs[2]);
await this.page1.tab(1);
break;

case 3:
// Do nothing to let Users write their single response answer
console.log({ chosenRandomNb }, ' <= User Response');
await this.page1.waitForSelector(ple.responseChoices, ELEMENT_WAIT_TIME);
await sleep(2000);
break;
}
const condition = chosenRandomNb === 0 || chosenRandomNb === 1 || chosenRandomNb === 2;
await this.page1.waitForSelector(ple.startPoll, ELEMENT_WAIT_TIME);
await this.page1.click(ple.startPoll, true);
await this.page2.waitForSelector(ple.pollingContainer, ELEMENT_WAIT_TIME);
console.log({ condition });
switch (condition) {
case true:
await this.page2.clickNItem(ple.pollAnswerOptionBtn, true, 2);
break;
case false:
await this.page2.page.focus(ple.pollAnswerOptionInput);
await this.page2.page.keyboard.type(customs[3]);
await this.page2.waitForSelector(ple.pollSubmitAnswer, ELEMENT_WAIT_TIME);
await this.page2.click(ple.pollSubmitAnswer, true);
break;
}
await this.page1.waitForSelector(ple.publishLabel, ELEMENT_WAIT_TIME);
await this.page1.click(ple.publishLabel, true);
await sleep(2000);
const receivedAnswerFound = await this.page1.page.evaluate(utilCustomParams.countTestElements, ple.receivedAnswer);
await sleep(2000);
return receivedAnswerFound;
} catch (e) {
console.log(e);
return false;
}
}

// Close all Pages
async close(page1, page2) {
await page1.close();
Expand Down