Added language test.

This commit is contained in:
SamTV12345 2024-03-11 19:14:41 +01:00
parent 0d7bca27c1
commit 129c25073c
8 changed files with 224 additions and 263 deletions

View file

@ -128,6 +128,8 @@ export const goToPad = async (page: Page, padId: string) => {
export const clearPadContent = async (page: Page) => { export const clearPadContent = async (page: Page) => {
const body = await getPadBody(page);
await body.click();
await page.keyboard.down('Control'); await page.keyboard.down('Control');
await page.keyboard.press('A'); await page.keyboard.press('A');
await page.keyboard.up('Control'); await page.keyboard.up('Control');

View file

@ -0,0 +1,20 @@
import {Page} from "@playwright/test";
/**
* Sets the src-attribute of the main iframe to the timeslider
* In case a revision is given, sets the timeslider to this specific revision.
* Defaults to going to the last revision.
* It waits until the timer is filled with date and time, because it's one of the
* last things that happen during timeslider load
*
* @param page
* @param {number} [revision] the optional revision
* @returns {Promise}
* @todo for some reason this does only work the first time, you cannot
* goto rev 0 and then via the same method to rev 5. Use buttons instead
*/
export const gotoTimeslider = async (page: Page, revision: number): Promise<any> => {
let revisionString = Number.isInteger(revision) ? `#${revision}` : '';
await page.goto(`${page.url()}/timeslider${revisionString}`);
await page.waitForSelector('#timer')
};

View file

@ -0,0 +1,85 @@
import {expect, test} from "@playwright/test";
import {getPadBody, goToNewPad} from "../helper/padHelper";
import {showSettings} from "../helper/settingsHelper";
test.beforeEach(async ({ page, browser })=>{
const context = await browser.newContext()
await context.clearCookies()
await goToNewPad(page);
})
test.describe('Language select and change', function () {
// Destroy language cookies
test('makes text german', async function ({page}) {
// click on the settings button to make settings visible
await showSettings(page)
// click the language button
await page.locator('.nice-select').nth(1).locator('.current').click()
await page.locator('.nice-select').locator('[data-value=de]').click()
//const $language = chrome$('#languagemenu');
//const $languageoption = $language.find('[value=de]');
// select german
await page.locator('.buttonicon-bold').evaluate((el) => el.parentElement!.title === 'Fett (Strg-B)');
});
test('makes text English', async function ({page}) {
await showSettings(page)
// click the language button
await page.locator('.nice-select').nth(1).locator('.current').click()
await page.locator('.nice-select').locator('[data-value=de]').click()
// select german
await page.locator('.buttonicon-bold').evaluate((el) => el.parentElement!.title === 'Fett (Strg-B)');
// change to english
await page.locator('.nice-select').nth(1).locator('.current').click()
await page.locator('.nice-select').locator('[data-value=en]').click()
// check if the language is now English
await page.locator('.buttonicon-bold').evaluate((el) => el.parentElement!.title !== 'Fett (Strg-B)');
});
test('changes direction when picking an rtl lang', async function ({page}) {
await showSettings(page)
// click the language button
await page.locator('.nice-select').nth(1).locator('.current').click()
await page.locator('.nice-select').locator('[data-value=de]').click()
// select german
await page.locator('.buttonicon-bold').evaluate((el) => el.parentElement!.title === 'Fett (Strg-B)');
// click the language button
await page.locator('.nice-select').nth(1).locator('.current').click()
// select arabic
// $languageoption.attr('selected','selected'); // Breaks the test..
await page.locator('.nice-select').locator('[data-value=ar]').click()
await page.waitForSelector('html[dir="rtl"]')
});
test('changes direction when picking an ltr lang', async function ({page}) {
await showSettings(page)
// change to english
await page.locator('.nice-select').nth(1).locator('.current').click()
await page.locator('.nice-select').locator('[data-value=en]').click()
// check if the language is now English
await page.locator('.buttonicon-bold').evaluate((el) => el.parentElement!.title !== 'Fett (Strg-B)');
await page.waitForSelector('html[dir="ltr"]')
});
});

View file

@ -0,0 +1,37 @@
import {expect, test} from "@playwright/test";
import {clearPadContent, getPadBody, goToNewPad, writeToPad} from "../helper/padHelper";
test.beforeEach(async ({ page })=>{
// create a new pad before each test run
await goToNewPad(page);
})
// deactivated, we need a nice way to get the timeslider, this is ugly
test.describe('timeslider button takes you to the timeslider of a pad', function () {
test('timeslider contained in URL', async function ({page}) {
const padBody = await getPadBody(page);
await clearPadContent(page)
await writeToPad(page, 'Foo'); // send line 1 to the pad
// get the first text element inside the editable space
const $firstTextElement = padBody.locator('div span').first();
const originalValue = await $firstTextElement.textContent(); // get the original value
await $firstTextElement.click()
await writeToPad(page, 'Testing'); // send line 1 to the pad
const modifiedValue = await $firstTextElement.textContent(); // get the modified value
expect(modifiedValue).not.toBe(originalValue); // expect the value to change
const $timesliderButton = page.locator('.buttonicon-history');
await $timesliderButton.click(); // So click the timeslider link
await page.waitForSelector('#timeslider-wrapper')
const iFrameURL = page.url(); // get the url
const inTimeslider = iFrameURL.indexOf('timeslider') !== -1;
expect(inTimeslider).toBe(true); // expect the value to change
});
});

View file

@ -0,0 +1,80 @@
'use strict';
import {expect, Page, test} from "@playwright/test";
import {clearPadContent, getPadBody, goToNewPad, writeToPad} from "../helper/padHelper";
import {gotoTimeslider} from "../helper/timeslider";
test.beforeEach(async ({ page })=>{
await goToNewPad(page);
})
test.describe('timeslider follow', function () {
// TODO needs test if content is also followed, when user a makes edits
// while user b is in the timeslider
test("content as it's added to timeslider", async function ({page}) {
// send 6 revisions
const revs = 6;
const message = 'a\n\n\n\n\n\n\n\n\n\n';
const newLines = message.split('\n').length;
for (let i = 0; i < revs; i++) {
await writeToPad(page, message)
}
await gotoTimeslider(page,0);
expect(page.url()).toContain('#0');
const originalTop = await page.evaluate(() => {
return window.document.querySelector('#innerdocbody')!.getBoundingClientRect().top;
});
// set to follow contents as it arrives
await page.check('#options-followContents');
await page.click('#playpause_button_icon');
// wait for the scroll
await page.waitForTimeout(1000)
const currentOffset = await page.evaluate(() => {
return window.document.querySelector('#innerdocbody')!.getBoundingClientRect().top;
});
console.log('originalTop', originalTop);
console.log('currentOffset', currentOffset);
expect(currentOffset).toBeLessThan(originalTop);
});
/**
* Tests for bug described in #4389
* The goal is to scroll to the first line that contains a change right before
* the change is applied.
*/
test('only to lines that exist in the pad view, regression test for #4389', async function ({page}) {
const padBody = await getPadBody(page)
await padBody.click()
await clearPadContent(page)
await writeToPad(page,'Test line\n' +
'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' +
'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' +
'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n');
await padBody.locator('div').nth(40).click();
await writeToPad(page, 'Another test line');
await gotoTimeslider(page, 200);
// set to follow contents as it arrives
await page.check('#options-followContents');
await page.waitForTimeout(1000)
const oldYPosition = await page.locator('#editorcontainerbox').evaluate((el) => {
return el.scrollTop;
})
expect(oldYPosition).toBe(0);
});
});

View file

@ -1,121 +0,0 @@
'use strict';
describe('Language select and change', function () {
// Destroy language cookies
window.Cookies.remove('language');
// create a new pad before each test run
beforeEach(async function () {
await helper.aNewPad();
});
// Destroy language cookies
it('makes text german', async function () {
this.timeout(1000);
const chrome$ = helper.padChrome$;
// click on the settings button to make settings visible
const $settingsButton = chrome$('.buttonicon-settings');
$settingsButton.trigger('click');
// click the language button
const $language = chrome$('#languagemenu');
const $languageoption = $language.find('[value=de]');
// select german
$languageoption.attr('selected', 'selected');
$language.trigger('change');
await helper.waitForPromise(
() => chrome$('.buttonicon-bold').parent()[0].title === 'Fett (Strg-B)');
// get the value of the bold button
const $boldButton = chrome$('.buttonicon-bold').parent();
// get the title of the bold button
const boldButtonTitle = $boldButton[0].title;
// check if the language is now german
expect(boldButtonTitle).to.be('Fett (Strg-B)');
});
it('makes text English', async function () {
this.timeout(1000);
const chrome$ = helper.padChrome$;
// click on the settings button to make settings visible
const $settingsButton = chrome$('.buttonicon-settings');
$settingsButton.trigger('click');
// click the language button
const $language = chrome$('#languagemenu');
// select english
$language.val('en');
$language.trigger('change');
// get the value of the bold button
let $boldButton = chrome$('.buttonicon-bold').parent();
await helper.waitForPromise(() => $boldButton[0].title !== 'Fett (Strg+B)');
// get the value of the bold button
$boldButton = chrome$('.buttonicon-bold').parent();
// get the title of the bold button
const boldButtonTitle = $boldButton[0].title;
// check if the language is now English
expect(boldButtonTitle).to.be('Bold (Ctrl+B)');
});
it('changes direction when picking an rtl lang', async function () {
// TODO: flaky
if (window.bowser.safari) {
this.timeout(5000);
} else {
this.timeout(1000);
}
const chrome$ = helper.padChrome$;
// click on the settings button to make settings visible
const $settingsButton = chrome$('.buttonicon-settings');
$settingsButton.trigger('click');
// click the language button
const $language = chrome$('#languagemenu');
const $languageoption = $language.find('[value=ar]');
// select arabic
// $languageoption.attr('selected','selected'); // Breaks the test..
$language.val('ar');
$languageoption.trigger('change');
await helper.waitForPromise(() => chrome$('html')[0].dir !== 'ltr');
// check if the document's direction was changed
expect(chrome$('html')[0].dir).to.be('rtl');
});
it('changes direction when picking an ltr lang', async function () {
const chrome$ = helper.padChrome$;
// click on the settings button to make settings visible
const $settingsButton = chrome$('.buttonicon-settings');
$settingsButton.trigger('click');
// click the language button
const $language = chrome$('#languagemenu');
const $languageoption = $language.find('[value=en]');
// select english
// select arabic
$languageoption.attr('selected', 'selected');
$language.val('en');
$languageoption.trigger('change');
await helper.waitForPromise(() => chrome$('html')[0].dir !== 'rtl');
// check if the document's direction was changed
expect(chrome$('html')[0].dir).to.be('ltr');
});
});

View file

@ -1,41 +0,0 @@
'use strict';
// deactivated, we need a nice way to get the timeslider, this is ugly
xdescribe('timeslider button takes you to the timeslider of a pad', function () {
beforeEach(async function () {
await helper.aNewPad();
});
it('timeslider contained in URL', async function () {
const inner$ = helper.padInner$;
const chrome$ = helper.padChrome$;
// get the first text element inside the editable space
const $firstTextElement = inner$('div span').first();
const originalValue = $firstTextElement.text(); // get the original value
$firstTextElement.sendkeys('Testing'); // send line 1 to the pad
const modifiedValue = $firstTextElement.text(); // get the modified value
expect(modifiedValue).not.to.be(originalValue); // expect the value to change
// The value has changed so we can..
await helper.waitForPromise(() => modifiedValue !== originalValue);
const $timesliderButton = chrome$('#timesliderlink');
$timesliderButton.trigger('click'); // So click the timeslider link
await helper.waitForPromise(() => {
const iFrameURL = chrome$.window.location.href;
if (iFrameURL) {
return iFrameURL.indexOf('timeslider') !== -1;
} else {
return false; // the URL hasnt been set yet
}
});
// click the buttons
const iFrameURL = chrome$.window.location.href; // get the url
const inTimeslider = iFrameURL.indexOf('timeslider') !== -1;
expect(inTimeslider).to.be(true); // expect the value to change
});
});

View file

@ -1,101 +0,0 @@
'use strict';
describe('timeslider follow', function () {
// create a new pad before each test run
beforeEach(async function () {
await helper.aNewPad();
});
// TODO needs test if content is also followed, when user a makes edits
// while user b is in the timeslider
it("content as it's added to timeslider", async function () {
this.timeout(20000);
// send 6 revisions
const revs = 6;
const message = 'a\n\n\n\n\n\n\n\n\n\n';
const newLines = message.split('\n').length;
for (let i = 0; i < revs; i++) {
await helper.edit(message, newLines * i + 1);
}
await helper.gotoTimeslider(0);
await helper.waitForPromise(() => helper.contentWindow().location.hash === '#0');
const originalTop = helper.contentWindow().$('#innerdocbody').offset();
// set to follow contents as it arrives
helper.contentWindow().$('#options-followContents').prop('checked', true);
helper.contentWindow().$('#playpause_button_icon').trigger('click');
let newTop;
await helper.waitForPromise(() => {
newTop = helper.contentWindow().$('#innerdocbody').offset();
return newTop.top < originalTop.top;
});
});
/**
* Tests for bug described in #4389
* The goal is to scroll to the first line that contains a change right before
* the change is applied.
*/
it('only to lines that exist in the pad view, regression test for #4389', async function () {
await helper.clearPad();
await helper.edit('Test line\n' +
'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' +
'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' +
'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n');
await helper.edit('Another test line', 40);
await helper.gotoTimeslider();
// set to follow contents as it arrives
helper.contentWindow().$('#options-followContents').prop('checked', true);
const oldYPosition = helper.contentWindow().$('#editorcontainerbox')[0].scrollTop;
expect(oldYPosition).to.be(0);
/**
* pad content rev 0 [default Pad text]
* pad content rev 1 ['']
* pad content rev 2 ['Test line','','', ..., '']
* pad content rev 3 ['Test line','',..., 'Another test line', ..., '']
*/
// line 40 changed
helper.contentWindow().$('#leftstep').trigger('click');
await helper.waitForPromise(() => hasFollowedToLine(40));
// line 1 is the first line that changed
helper.contentWindow().$('#leftstep').trigger('click');
await helper.waitForPromise(() => hasFollowedToLine(1));
// line 1 changed
helper.contentWindow().$('#leftstep').trigger('click');
await helper.waitForPromise(() => hasFollowedToLine(1));
// line 1 changed
helper.contentWindow().$('#rightstep').trigger('click');
await helper.waitForPromise(() => hasFollowedToLine(1));
// line 1 is the first line that changed
helper.contentWindow().$('#rightstep').trigger('click');
await helper.waitForPromise(() => hasFollowedToLine(1));
// line 40 changed
helper.contentWindow().$('#rightstep').trigger('click');
helper.waitForPromise(() => hasFollowedToLine(40));
});
});
/**
* @param {number} lineNum
* @returns {boolean} scrolled to the lineOffset?
*/
const hasFollowedToLine = (lineNum) => {
const scrollPosition = helper.contentWindow().$('#editorcontainerbox')[0].scrollTop;
const lineOffset =
helper.contentWindow().$('#innerdocbody').find(`div:nth-child(${lineNum})`)[0].offsetTop;
return Math.abs(scrollPosition - lineOffset) < 1;
};