Skip to content

Commit cfc627d

Browse files
committed
Merge branch 'develop' of github.com:Emurgo/yoroi-frontend into feat/YOEXT-1693/notifications-logic
2 parents b749126 + 9bdb687 commit cfc627d

24 files changed

+298
-174
lines changed

packages/e2e-tests/helpers/mock-dApp-webpage/mockServer.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,14 @@ export const getMockServer = settings => {
2626
`);
2727
});
2828

29-
const mockServer = server.listen(mockedServerPorts, () => {
30-
console.log(`JSON Server is running at http://localhost:${mockedServerPorts}`);
31-
});
29+
return new Promise((resolve, reject) => {
30+
const mockServer = server.listen(mockedServerPorts, () => {
31+
console.log(`JSON Server is running at http://localhost:${mockedServerPorts}`);
32+
resolve(mockServer);
33+
});
3234

33-
return mockServer;
34-
};
35+
mockServer.on('error', (err) => {
36+
reject(err);
37+
});
38+
});
39+
};

packages/e2e-tests/package-lock.json

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/e2e-tests/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
"@emurgo/cardano-serialization-lib-nodejs": "13.2.1",
4848
"bignumber.js": "^9.1.2",
4949
"chai": "^4.3.10",
50-
"chromedriver": "133.0.2",
50+
"chromedriver": "134.0.0",
5151
"cross-env": "^7.0.3",
5252
"json-server": "^0.17.4",
5353
"mocha": "^10.2.0",

packages/e2e-tests/pages/basepage.js

+54-30
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class BasePage {
4040
};
4141

4242
async goToUrl(theURL) {
43-
this.logger.info('BasePage::goToUrl is called');
43+
this.logger.info(`BasePage::goToUrl is called. "${theURL}"`);
4444
await this.driver.get(theURL);
4545
}
4646
async refreshPage() {
@@ -63,7 +63,18 @@ class BasePage {
6363
}
6464
async click(locator) {
6565
this.logger.info(`BasePage::click is called. Locator: ${JSON.stringify(locator)}`);
66-
await this.driver.findElement(getByLocator(locator)).click();
66+
let element = await this.driver.findElement(getByLocator(locator));
67+
try {
68+
await element.click();
69+
} catch (error) {
70+
if (error.name === 'StaleElementReferenceError') {
71+
this.logger.info(`BasePage::click Re-try because of StaleElementReferenceError`);
72+
element = await this.driver.findElement(getByLocator(locator));
73+
await element.click();
74+
} else {
75+
throw error;
76+
}
77+
}
6778
}
6879
async clickByScript(locator) {
6980
this.logger.info(`BasePage::clickByScript is called. Locator: ${JSON.stringify(locator)}`);
@@ -86,6 +97,10 @@ class BasePage {
8697
const clickable = await this.findElement(locator);
8798
await this.driver.executeScript('arguments[0].scrollIntoView()', clickable);
8899
}
100+
async scrollIntoViewElement(webElement) {
101+
this.logger.info(`BasePage::scrollIntoViewElement is called.`);
102+
await this.driver.executeScript('arguments[0].scrollIntoView()', webElement);
103+
}
89104
async findElement(locator) {
90105
this.logger.info(`BasePage::findElement is called. Locator: ${JSON.stringify(locator)}`);
91106
return await this.driver.findElement(getByLocator(locator));
@@ -96,13 +111,20 @@ class BasePage {
96111
}
97112
async getText(locator) {
98113
this.logger.info(`BasePage::getText is called. Locator: ${JSON.stringify(locator)}`);
99-
return await this.waitPresentedAndAct(
100-
locator,
101-
async () => {
102-
const locatorElem = await this.findElement(locator);
103-
return await locatorElem.getText();
114+
return await this.waitPresentedAndAct(locator, async () => {
115+
let element = await this.findElement(locator);
116+
try {
117+
return await element.getText();
118+
} catch (error) {
119+
if (error.name === 'StaleElementReferenceError') {
120+
this.logger.info(`BasePage::getText Re-try because of StaleElementReferenceError`);
121+
element = await this.findElement(locator);
122+
return await element.getText();
123+
} else {
124+
throw error;
125+
}
104126
}
105-
);
127+
});
106128
}
107129
async getCssValue(locator, cssStyleProperty) {
108130
this.logger.info(
@@ -167,9 +189,7 @@ class BasePage {
167189
await input.sendKeys(value);
168190
}
169191
async inputElem(webElement, value) {
170-
this.logger.info(
171-
`BasePage::inputElem is called. Value: ${value}`
172-
);
192+
this.logger.info(`BasePage::inputElem is called. Value: ${value}`);
173193
await webElement.sendKeys(value);
174194
}
175195
async clearInput(locator) {
@@ -200,7 +220,9 @@ class BasePage {
200220
await input.sendKeys(Key.BACK_SPACE);
201221
}
202222
async setImplicitTimeout(timeoutMs, functionName) {
203-
this.logger.info(`BasePage::setImplicitTimeout is called. Function: ${functionName}. Timeout: ${timeoutMs}`);
223+
this.logger.info(
224+
`BasePage::setImplicitTimeout is called. Function: ${functionName}. Timeout: ${timeoutMs}`
225+
);
204226
await this.driver.manage().setTimeouts({ implicit: timeoutMs });
205227
}
206228
async getFromLocalStorage(key) {
@@ -252,7 +274,7 @@ class BasePage {
252274
const jsonLogsStrings = logEntries.map(l => {
253275
const splitMsg = l.message.split(' ');
254276
const message = splitMsg.slice(2).join(' ');
255-
return `[${l.level}] [${l.timestamp}] ${message}`
277+
return `[${l.level}] [${l.timestamp}] ${message}`;
256278
});
257279
await writeFile(logsPaths, jsonLogsStrings.join(',\n'));
258280
}
@@ -266,7 +288,9 @@ class BasePage {
266288
.manage()
267289
.logs()
268290
.get(logging.Type.DRIVER, logging.Level.INFO);
269-
const driverLogsStrings = driverLogEntries.map(l =>`[${l.level}] [${l.timestamp}] ${l.message}`);
291+
const driverLogsStrings = driverLogEntries.map(
292+
l => `[${l.level}] [${l.timestamp}] ${l.message}`
293+
);
270294
await writeFile(driverLogsPaths, driverLogsStrings.join(''));
271295
}
272296
async waitForElementLocated(locator) {
@@ -447,22 +471,22 @@ class BasePage {
447471
}
448472
async getInfoFromIndexedDBFF(tableName) {
449473
this.logger.info(`BasePage::getInfoFromIndexedDBFF Table name "${tableName}"`);
450-
await this.driver.executeScript(
451-
(table) => {
452-
const dbName = 'yoroi-schema';
453-
const dbRequest = window.indexedDB.open(dbName);
454-
dbRequest.onsuccess = function (event) {
455-
const db = event.target.result;
456-
// without that it doesn't work
457-
window.dataBase = db;
458-
const tableContentRequest = db.transaction(table, 'readonly').objectStore(table).mozGetAll();
459-
tableContentRequest.onsuccess = function (event) {
460-
window.tableData = event.target.result;
461-
};
474+
await this.driver.executeScript(table => {
475+
const dbName = 'yoroi-schema';
476+
const dbRequest = window.indexedDB.open(dbName);
477+
dbRequest.onsuccess = function (event) {
478+
const db = event.target.result;
479+
// without that it doesn't work
480+
window.dataBase = db;
481+
const tableContentRequest = db
482+
.transaction(table, 'readonly')
483+
.objectStore(table)
484+
.mozGetAll();
485+
tableContentRequest.onsuccess = function (event) {
486+
window.tableData = event.target.result;
462487
};
463-
},
464-
tableName
465-
);
488+
};
489+
}, tableName);
466490
let tableContent;
467491
try {
468492
// without that it doesn't work
@@ -601,7 +625,7 @@ class BasePage {
601625
},
602626
'yoroi-schema',
603627
tableName,
604-
valueItem,
628+
valueItem
605629
);
606630
}
607631
}

packages/e2e-tests/pages/wallet/walletTab/transactionsModals/exportTransactionModal.page.js

+23-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import BasePage from '../../../basepage.js';
2-
import { twoSeconds, quarterSecond } from '../../../../helpers/timeConstants.js';
2+
import {
3+
twoSeconds,
4+
quarterSecond,
5+
defaultWaitTimeout,
6+
halfSecond,
7+
} from '../../../../helpers/timeConstants.js';
38
import { isHeadless, isLinux } from '../../../../utils/utils.js';
49

510
class ExportTransactionsModal extends BasePage {
@@ -45,19 +50,19 @@ class ExportTransactionsModal extends BasePage {
4550
exportUbuntuPenIconButtonLocator = {
4651
locator: '.MuiPickersToolbar-penIconButton',
4752
method: 'css',
48-
}
53+
};
4954
exportUbuntuClickInputLocator = {
5055
locator: '.MuiInputBase-formControl',
5156
method: 'css',
52-
}
57+
};
5358
exportUbuntuDateInputLocator = {
5459
locator: '.MuiOutlinedInput-input',
5560
method: 'css',
56-
}
61+
};
5762
exportUbuntuOkButtonLocator = {
5863
locator: 'div.MuiDialogActions-root > button:nth-child(2)',
5964
method: 'css',
60-
}
65+
};
6166
// methods
6267
async isDisplayed() {
6368
this.logger.info(`ExportTransactionsModal::isDisplayed is called`);
@@ -75,7 +80,19 @@ class ExportTransactionsModal extends BasePage {
7580
return false;
7681
}
7782
}
78-
async _ubuntuHeadlessSetDate(dateString){
83+
async isNotDisplayed() {
84+
this.logger.info(`ExportTransactionsModal::isNotDisplayed is called`);
85+
const modalWindowIsNotPresented = await this.customWaitIsNotPresented(
86+
this.exportDialogWindowLocator,
87+
defaultWaitTimeout,
88+
halfSecond
89+
);
90+
this.logger.info(
91+
`ExportTransactionsModal::isNotDisplayed The export modal is displayed: ${modalWindowIsNotPresented}`
92+
);
93+
return modalWindowIsNotPresented;
94+
}
95+
async _ubuntuHeadlessSetDate(dateString) {
7996
await this.waitForElement(this.exportUbuntuPenIconButtonLocator);
8097
await this.click(this.exportUbuntuPenIconButtonLocator);
8198

@@ -137,7 +154,6 @@ class ExportTransactionsModal extends BasePage {
137154
async exportTransactionsFile() {
138155
this.logger.info(`ExportTransactionsModal::exportTransactionsFile is called`);
139156
await this.click(this.exportTransactionsButtonLocator);
140-
await this.sleep(twoSeconds + twoSeconds);
141157
}
142158
async getStartDateInputBorderColor() {
143159
this.logger.info(`ExportTransactionsModal::getStartDateInputBorderColor is called`);

packages/e2e-tests/pages/wallet/walletTab/walletTransactions.page.js

+60-16
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,10 @@ export class TransactionsSubTab extends WalletTab {
191191
fiveSeconds,
192192
quarterSecond
193193
);
194-
const [submenuState, summaryState] = await Promise.all([submenuStatePromise, summaryStatePromise]);
194+
const [submenuState, summaryState] = await Promise.all([
195+
submenuStatePromise,
196+
summaryStatePromise,
197+
]);
195198

196199
return submenuState && summaryState;
197200
}
@@ -342,6 +345,38 @@ export class TransactionsSubTab extends WalletTab {
342345
}
343346
return txsAmount;
344347
}
348+
async scrollIntoViewLastTx() {
349+
this.logger.info(`TransactionsSubTab::scrollIntoViewLastTx is called`);
350+
const allGroups = await this.__getTxsGroups();
351+
let lastTx = null;
352+
for (const txGroup of allGroups) {
353+
const allTxs = await this.findElements(this.txsInGroupLocator(txGroup.groupIndex));
354+
lastTx = allTxs[allTxs.length - 1];
355+
}
356+
await this.scrollIntoViewElement(lastTx);
357+
}
358+
async showMoreOrLoaderDisplayed() {
359+
this.logger.info(`TransactionsSubTab::showMoreOrLoaderDisplayed is called`);
360+
const commonTimeout = fiveSeconds;
361+
const showMoreStatePromise = this.customWaitIsPresented(
362+
this.showMoreTxsButtonLocator,
363+
commonTimeout,
364+
quarterSecond
365+
);
366+
const loaderStatePromise = this.customWaitIsPresented(
367+
this.txsLoaderSpinnerLocator,
368+
commonTimeout,
369+
quarterSecond
370+
);
371+
const state = await Promise.any([showMoreStatePromise, loaderStatePromise]);
372+
if (state) {
373+
this.logger.info(`TransactionsSubTab::showMoreOrLoaderDisplayed Show more or loader is displayed`);
374+
return true;
375+
} else {
376+
this.logger.warn(`TransactionsSubTab::showMoreOrLoaderDisplayed Nothing is not displayed`);
377+
return false;
378+
}
379+
}
345380
async showMoreBtnIsDisplayed() {
346381
this.logger.info(`TransactionsSubTab::showMoreBtnIsDisplayed is called`);
347382
const state = await this.customWaitIsPresented(
@@ -395,36 +430,45 @@ export class TransactionsSubTab extends WalletTab {
395430
return true;
396431
}
397432
async _loadMore() {
398-
const showMoreIsDisplayed = await this.showMoreBtnIsDisplayed();
399-
if (showMoreIsDisplayed) {
400-
return await this._pressShowMoreTransactions();
401-
}
402-
const loaderIsDisplayed = await this.loaderIsDisplayed();
403-
if (loaderIsDisplayed) {
404-
const thirtySec = 3 * defaultWaitTimeout;
405-
await this.scrollIntoView(this.txsLoaderSpinnerLocator);
406-
const result = await this.waitTxLoaderIsNotDisplayed(thirtySec, quarterSecond);
407-
if (!result) {
408-
throw new Error(`Transactions are still loading after ${thirtySec / 1000} seconds`);
409-
}
410-
const btnIsDisplayed = await this.showMoreBtnIsDisplayed();
411-
if (btnIsDisplayed) {
433+
const somethingIsDisplayed = await this.showMoreOrLoaderDisplayed();
434+
if(somethingIsDisplayed) {
435+
const showMoreIsDisplayed = await this.showMoreBtnIsDisplayed();
436+
if (showMoreIsDisplayed) {
412437
return await this._pressShowMoreTransactions();
413438
}
439+
const loaderIsDisplayed = await this.loaderIsDisplayed();
440+
if (loaderIsDisplayed) {
441+
const thirtySec = 3 * defaultWaitTimeout;
442+
await this.scrollIntoView(this.txsLoaderSpinnerLocator);
443+
const result = await this.waitTxLoaderIsNotDisplayed(thirtySec, quarterSecond);
444+
if (!result) {
445+
throw new Error(`Transactions are still loading after ${thirtySec / 1000} seconds`);
446+
}
447+
const btnIsDisplayed = await this.showMoreBtnIsDisplayed();
448+
if (btnIsDisplayed) {
449+
return await this._pressShowMoreTransactions();
450+
}
451+
}
414452
}
415-
this.logger.warn(`TransactionsSubTab::_loadMore There are no Show More Transactions button and no loader`);
453+
this.logger.warn(
454+
`TransactionsSubTab::_loadMore There are no Show More Transactions button and no loader`
455+
);
416456
return false;
417457
}
418458
async loadMoreTxs(amountOfLoads = 1) {
419459
this.logger.info(`TransactionsSubTab::loadMoreTxs is called. Amount of loads ${amountOfLoads}`);
420460
for (let tryNumber = 0; tryNumber < amountOfLoads; tryNumber++) {
461+
this.logger.info(`TransactionsSubTab::loadMoreTxs Try number ${tryNumber}`);
462+
await this.scrollIntoViewLastTx();
421463
const canLoadMore = await this._loadMore();
464+
this.logger.info(`TransactionsSubTab::loadMoreTxs Can load more txs ${canLoadMore}`);
422465
if (!canLoadMore) {
423466
break;
424467
}
425468
await this.sleep(oneSecond);
426469
}
427470
const thirtySec = 3 * defaultWaitTimeout;
471+
await this.scrollIntoViewLastTx();
428472
await this.waitTxLoaderIsNotDisplayed(thirtySec, quarterSecond);
429473
}
430474
async downloadAllTxs() {

packages/e2e-tests/test/09_exportTransactions.test.js

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ describe('Export transactions, positive', function () {
5151
const btnEnabled = await exportDialog.exportButtonIsEnabled();
5252
expect(btnEnabled, 'The export button is not enabled').to.be.true;
5353
await exportDialog.exportTransactionsFile();
54+
const exportDialogState = await exportDialog.isNotDisplayed();
55+
expect(exportDialogState, 'The export dialog is still displayed').to.be.true;
5456
});
5557
// Check the exported file
5658
it('Checking the exported file', async function () {

0 commit comments

Comments
 (0)