From cb49c1e5e1ce57f0be1a788cf51964714c203b70 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Sat, 12 May 2018 23:44:19 -0400 Subject: [PATCH] Improved e2e tests --- e2e/address-detail/address-detail.e2e-spec.ts | 75 +++++++---- e2e/address-detail/address-detail.po.ts | 87 +++++-------- e2e/block-details/block-details.e2e-spec.ts | 65 ++++++---- e2e/block-details/block-details.po.ts | 84 ++++--------- e2e/blocks/blocks.e2e-spec.ts | 103 ++++++++++++---- e2e/blocks/blocks.po.ts | 116 +++++++++++------- e2e/general.po.ts | 72 +++++++++++ e2e/navigation/navigation.e2e-spec.ts | 41 +++++++ e2e/navigation/navigation.po.ts | 31 +++++ e2e/richlist/richlist.e2e-spec.ts | 29 ++++- e2e/richlist/richlist.po.ts | 44 ++++--- e2e/search/search.e2e-spec.ts | 32 ++++- e2e/search/search.po.ts | 10 ++ .../transaction-detail.e2e-spec.ts | 57 ++++++--- .../transaction-detail.po.ts | 63 ++-------- .../unconfirmed-transactions.e2e-spec.ts | 11 +- .../unconfirmed-transactions.po.ts | 25 +--- .../unspent-outputs.e2e-spec.ts | 51 +++++--- e2e/unspent-outputs/unspent-outputs.po.ts | 75 +++-------- .../address-detail.component.html | 2 +- 20 files changed, 638 insertions(+), 435 deletions(-) create mode 100644 e2e/general.po.ts create mode 100644 e2e/navigation/navigation.e2e-spec.ts create mode 100644 e2e/navigation/navigation.po.ts create mode 100644 e2e/search/search.po.ts diff --git a/e2e/address-detail/address-detail.e2e-spec.ts b/e2e/address-detail/address-detail.e2e-spec.ts index 4e7beabd..05d5d5e1 100644 --- a/e2e/address-detail/address-detail.e2e-spec.ts +++ b/e2e/address-detail/address-detail.e2e-spec.ts @@ -1,38 +1,71 @@ import { AddressDetailPage } from './address-detail.po'; +import { GeneralPageFunctions } from "../general.po"; describe('skycoin-explorer Address Page', () => { const page = new AddressDetailPage(); + const generalFunctions = new GeneralPageFunctions(); beforeEach(() => { }); - it('should show the Address Text and its length should be l>26 and l<36', () => { - page.navigateTo(); - let address = page.getAddressText(); - expect(address).toBeLessThan(36); - expect(address).toBeGreaterThan(26); + it('should display the correct title', () => { + generalFunctions.navigateTo('/app/address/24ooGeabUGQLnJmoyviqA8h2y7Cgz2CY4x7'); + expect(generalFunctions.getPageTitle()).toBe("24ooGeabUGQLnJmoyviqA8h2y7Cgz2CY4x7"); }); - it('should show the Address Info row and its length should be 5', () => { - page.navigateTo(); - expect(page.getAddressInfo()).toEqual(5); + it('should have the title for small screens', () => { + expect(page.getPageTitleForSmallScreens()).toBe("Address"); }); - it('should show the Transactions Rows and its length should be more than 0', () => { - page.navigateTo(); - expect(page.getTransactions()).toBe(true); + it('should have 5 address details rows', () => { + expect(generalFunctions.getDetailsRowCount()).toEqual(5); }); - it('should show One Transaction Input and its length should be l>26 and l<36', () => { - page.navigateTo(); - let inputAddress = page.getOneTransactionInput(); - expect(inputAddress).toBeLessThan(36); - expect(inputAddress).toBeGreaterThan(26); + it('should have the correct address for small screens', () => { + expect(page.getAddressForSmallScreens()).toEqual("24ooGeabUGQLnJmoyviqA8h2y7Cgz2CY4x7"); }); - it('should show tOne Transaction Output and its length should be l>26 and l<36', () => { - page.navigateTo(); - let outputAddress = page.getOneTransactionOutput(); - expect(outputAddress).toBeLessThan(36); - expect(outputAddress).toBeGreaterThan(26); + it('should show the correct # of transactions', () => { + expect(page.getNumberOfTransactions()).toBe(1); + }); + + it('should show the correct received amount', () => { + expect(page.getTotalReceived()).toBe(0.001); + }); + + it('should show the correct current balance', () => { + expect(page.getCurrentBalance()).toBe(0.001); + }); + + it('should show the correct transaction ID', () => { + expect(generalFunctions.getTransactionId(0)).toEqual('f375dfb0cea3f082daa03341f6283a483a9857206442feabc94f2b05b1df1fab'); + }); + + it('should show a valid transaction date', () => { + expect(generalFunctions.getTransactionDateValidity(0)).toBeTruthy(); + }); + + it('should show the correct transaction inputs', () => { + expect(generalFunctions.getTransactionInputs(0)).toBe('TXXyvkvs7Lt3EFtvTh51i4BagiJaGARsva'); + }); + + it('should show the correct transaction outputs', () => { + expect(generalFunctions.getTransactionOutputs(0)).toBe('24ooGeabUGQLnJmoyviqA8h2y7Cgz2CY4x7,TXXyvkvs7Lt3EFtvTh51i4BagiJaGARsva'); + }); + + it('should have the correct coins amount', () => { + expect(generalFunctions.getTransactionInputsAndOutputsTotalCoins()).toBe(6.002); + }); + + it('should show the correct final address balance', () => { + expect(page.getFinalBalance(0)).toBe(0.001); + }); + + it('should show the correct balance variation', () => { + expect(page.getBalanceChange(0)).toBe(0.001); + }); + + it('should show the error message', () => { + generalFunctions.navigateTo('/app/address/24ooGeabUGQLnJmoyviqA8h2y7Cgz2CY4x8'); + expect(generalFunctions.getErrorMessage()).toBeDefined(); }); }); \ No newline at end of file diff --git a/e2e/address-detail/address-detail.po.ts b/e2e/address-detail/address-detail.po.ts index 16b0b97c..89e58cb2 100644 --- a/e2e/address-detail/address-detail.po.ts +++ b/e2e/address-detail/address-detail.po.ts @@ -1,72 +1,49 @@ import { browser, by, element } from 'protractor'; export class AddressDetailPage { - navigateTo() { - return browser.get('/'); + getPageTitleForSmallScreens() { + return element(by.css('.element-details-wrapper > h2:nth-child(2)')) + .getAttribute('textContent'); } - goToAddressPage() { - return element(by.css('.table a.-row')) - .click() - .then(() => { - return element(by.css('.transaction > .-data > .row > div:nth-of-type(2) a')) - .click(); - }); + getAddressForSmallScreens() { + return element(by.css('.element-details > div:nth-of-type(1) > span:nth-of-type(2)')) + .getAttribute('textContent'); } - getAddressText() { - return this.goToAddressPage().then(() => { - return element(by.css('.element-details-wrapper h2:nth-of-type(1)')) - .getText() - .then(text => text.length); - }); + getNumberOfTransactions() { + return element(by.css('.element-details > div:nth-of-type(2) > div')) + .getText() + .then(text => Number(text)); } - getAddressInfo() { - return this.goToAddressPage().then(() => { - return element - .all(by.css('.element-details > div')) - .count() - .then(count => count); - }); + getTotalReceived() { + return element(by.css('.element-details > div:nth-of-type(3) > div')) + .getText() + .then(text => Number(text.replace(new RegExp(',', 'g'), ''))); } - getTransactions() { - return this.goToAddressPage().then(() => { - return element - .all(by.css('.transaction')) - .count() - .then(count => count > 0); - }); + getCurrentBalance() { + return element(by.css('.element-details > div:nth-of-type(3) > div')) + .getText() + .then(text => Number(text.replace(new RegExp(',', 'g'), ''))); } - getOneTransactionId() { - return this.goToAddressPage().then(() => { - return element - .all(by.css('.transaction .-title .col-sm-8.-left a')) - .get(0) - .getText() - .then(text => text.length); - }); + getFinalBalance(transsactionIndex: number) { + return element + .all(by.css('.transaction')) + .get(transsactionIndex) + .element(by.css('.-final-balance > div > div:nth-of-type(3)')) + .getText() + .then(text => Number(text.replace(new RegExp(',', 'g'), ''))); } - getOneTransactionInput() { - return this.goToAddressPage().then(() => { - return element - .all(by.css('.transaction > .-data > .row > div:nth-of-type(1) a')) - .get(0) - .getText() - .then(text => text.length); - }); - } - - getOneTransactionOutput() { - return this.goToAddressPage().then(() => { - return element - .all(by.css('.transaction > .-data > .row > div:nth-of-type(2) a')) - .get(0) - .getText() - .then(text => text.length); - }); + getBalanceChange(transsactionIndex: number) { + return element + .all(by.css('.transaction')) + .get(transsactionIndex) + .element(by.css('.-label')) + .getText() + .then(text => Number(text.split(' ')[0].replace(new RegExp(',', 'g'), ''))); } } \ No newline at end of file diff --git a/e2e/block-details/block-details.e2e-spec.ts b/e2e/block-details/block-details.e2e-spec.ts index 73f24073..cb5c32e6 100644 --- a/e2e/block-details/block-details.e2e-spec.ts +++ b/e2e/block-details/block-details.e2e-spec.ts @@ -1,46 +1,63 @@ import { BlockDetailsPage } from './block-details.po'; +import { GeneralPageFunctions } from "../general.po"; describe('skycoin-explorer Block Details Page', () => { const page = new BlockDetailsPage(); + const generalFunctions = new GeneralPageFunctions(); beforeEach(() => { }); - it('should display block details text', () => { - page.navigateTo(); - expect(page.getOneBlockDetailsText()).toEqual('Block Details'); + it('should display the title', () => { + generalFunctions.navigateTo('/app/block/5'); + expect(generalFunctions.getPageTitle()).toEqual('Block Details'); }); it('should display 6 block details rows', () => { - page.navigateTo(); - expect(page.getDetailsRow()).toEqual(6); + expect(generalFunctions.getDetailsRowCount()).toEqual(6); }); - it('should show the details of the Hash and its length should be 64', () => { - page.navigateTo(); - expect(page.getHash()).toEqual(64); + it('should show the correct block hight', () => { + expect(page.getBlockHeight()).toBe(5); }); - it('should show the details of the Parent Hash and its length should be 64', () => { - page.navigateTo(); - expect(page.getParentHash()).toEqual(64); + it('should show a valid timestamp', () => { + expect(page.getTimestampValidity()).toBeTruthy(); }); - it('should show the Transaction Id and its length should be 64', () => { - page.navigateTo(); - expect(page.getTransactionId()).toEqual(64); + it('should show the correct size', () => { + expect(page.getSize()).toBe(317); }); - it('should show one Transaction Input address and its length should be l>26 and l<36', () => { - page.navigateTo(); - let inputAddress = page.getOneTransactionInput(); - expect(inputAddress).toBeLessThan(36); - expect(inputAddress).toBeGreaterThan(26); + it('should show the correct block hash', () => { + expect(page.getBlockHash()).toEqual("114fe60587a158428a47e0f9571d764f495912c299aa4e67fc88004cf21b0c24"); }); - it('should show One Transaction Output address and its length should be l>26 and l<36', () => { - page.navigateTo(); - let outputAddress = page.getOneTransactionOutput(); - expect(outputAddress).toBeLessThan(36); - expect(outputAddress).toBeGreaterThan(26); + it('should show the correct parent block hash', () => { + expect(page.getParentHash()).toEqual("415e47348a1e642cb2e31d00ee500747d3aed0336aabfff7d783ed21465251c7"); + }); + + it('should show the correct amount', () => { + expect(page.getAmount()).toBe(999990); + }); + + it('should show the correct transaction ID', () => { + expect(generalFunctions.getTransactionId(0)).toEqual('0579e7727627cd9815a8a8b5e1df86124f45a4132cc0dbd00d2f110e4f409b69'); + }); + + it('should show the correct transaction inputs', () => { + expect(generalFunctions.getTransactionInputs(0)).toBe('R6aHqKWSQfvpdo2fGSrq4F1RYXkBWR9HHJ,R6aHqKWSQfvpdo2fGSrq4F1RYXkBWR9HHJ'); + }); + + it('should show the correct transaction outputs', () => { + expect(generalFunctions.getTransactionOutputs(0)).toBe('R6aHqKWSQfvpdo2fGSrq4F1RYXkBWR9HHJ,2fGC7kwAM9yZyEF1QqBqp8uo9RUsF6ENGJF'); + }); + + it('should have the correct coins amount', () => { + expect(generalFunctions.getTransactionInputsAndOutputsTotalCoins()).toBe(1999980); + }); + + it('should show the error message', () => { + generalFunctions.navigateTo('/app/block/-1'); + expect(generalFunctions.getErrorMessage()).toBeDefined(); }); }); \ No newline at end of file diff --git a/e2e/block-details/block-details.po.ts b/e2e/block-details/block-details.po.ts index a5f2106e..fdeb37b8 100644 --- a/e2e/block-details/block-details.po.ts +++ b/e2e/block-details/block-details.po.ts @@ -1,76 +1,42 @@ import { browser, by, element } from 'protractor'; export class BlockDetailsPage { - navigateTo() { - return browser.get('/'); - } - goToOneBlockDetails() { - return element(by.css('.table a.-row')).click(); + getBlockHeight() { + return element(by.css('.element-details > div:nth-of-type(1) > div')) + .getText() + .then(text => Number(text)); } - getOneBlockDetailsText() { - return this.goToOneBlockDetails().then(() => { - return element(by.css('.element-details-wrapper h2')).getText(); - }); + getTimestampValidity() { + return element(by.css('.element-details > div:nth-of-type(2) > div')) + .getText() + .then(text => !isNaN((new Date(text)).getTime())); } - getDetailsRow() { - return this.goToOneBlockDetails().then(() => { - return element - .all(by.css('.element-details .-row')) - .count() - .then(count => { - return count; - }); - }); + getSize() { + return element(by.css('.element-details > div:nth-of-type(3) > div')) + .getText() + .then(text => Number(text.split(' ')[0])); } - getHash() { - return this.goToOneBlockDetails().then(() => { - return element - .all(by.css('.element-details .-row a.-link')) - .get(0) - .getText() - .then(text => text.length); - }); + getBlockHash() { + return element + .all(by.css('.element-details .-row a.-link')) + .get(0) + .getText(); } getParentHash() { - return this.goToOneBlockDetails().then(() => { - return element - .all(by.css('.element-details .-row a.-link')) - .get(1) - .getText() - .then(text => text.length); - }); - } - - getTransactionId() { - return this.goToOneBlockDetails().then(() => { - return element(by.css('.transaction .-row a')) - .getText() - .then(text => text.length); - }); - } - - getOneTransactionInput() { - return this.goToOneBlockDetails().then(() => { - return element - .all(by.css('.transaction > .-data > .row > div:nth-of-type(1) a')) - .get(0) - .getText() - .then(text => text.length); - }); + return element + .all(by.css('.element-details .-row a.-link')) + .get(1) + .getText(); } - getOneTransactionOutput() { - return this.goToOneBlockDetails().then(() => { - return element - .all(by.css('.transaction > .-data > .row > div:nth-of-type(2) a')) - .get(0) - .getText() - .then(text => text.length); - }); + getAmount() { + return element(by.css('.element-details > div:nth-of-type(6) > div')) + .getText() + .then(text => Number(text.split(' ')[0].replace(new RegExp(',', 'g'), ''))); } } \ No newline at end of file diff --git a/e2e/blocks/blocks.e2e-spec.ts b/e2e/blocks/blocks.e2e-spec.ts index d9b89d4c..05cb19b8 100644 --- a/e2e/blocks/blocks.e2e-spec.ts +++ b/e2e/blocks/blocks.e2e-spec.ts @@ -1,48 +1,107 @@ import { BlocksPage } from './blocks.po'; +import { GeneralPageFunctions } from "../general.po"; describe('skycoin-explorer Blocks Page', () => { const page = new BlocksPage(); + const generalFunctions = new GeneralPageFunctions(); beforeEach(() => { }); - it('should display Blocks text', () => { - page.navigateTo(); - expect(page.getBlocksText()).toEqual('Blocks'); + it('should display the title for big screens', () => { + generalFunctions.navigateTo('/'); + expect(page.getPageTitle(0)).toBe("Blocks"); }); - it('should display Unconfirmed Transactions text', () => { - page.navigateTo(); + it('should display the first title for small screens', () => { + expect(page.getPageTitle(1)).toBe("Stats"); + }); + + it('should display the second title for small screens', () => { + expect(page.getPageTitle(2)).toBe("Blocks"); + }); + + it('should display the Unconfirmed Transactions link', () => { expect(page.getUnconfirmedTransactionsText()).toEqual('Unconfirmed Transactions'); }); - it('should display Rich List text', () => { - page.navigateTo(); + it('should display the Rich List link', () => { expect(page.getRichListText()).toEqual('Rich List'); }); - it('should contain 5 Details Blocks Labels', () => { - page.navigateTo(); - expect(page.getDetailsLabelsCount()).toEqual(5); + it('should contain 5 stats labels', () => { + expect(page.getStatsLabelsCount()).toEqual(5); }); - it('should contain 5 Details Blocks Values', () => { - page.navigateTo(); - expect(page.getDetailsValuesCount()).toEqual(5); + it('should contain valid stat values', () => { + expect(page.getStat(0)).toBeGreaterThan(0); + expect(page.getStat(1)).toBeGreaterThan(0); + expect(page.getStat(2)).toBeGreaterThan(0); + expect(page.getStat(3)).toBeGreaterThan(0); + expect(page.getStat(4)).toBeGreaterThan(0); }); - it('should contain 10 Blocks Items', () => { - page.navigateTo(); - expect(page.getBlocksListCount()).toEqual(10); + it('should contain 10 blocks items', () => { + expect(page.getBlocksListRowCount()).toEqual(10); }); - it('should contain a Blocks Pagination', () => { - page.navigateTo(); - expect(page.getPagination()).toBe(true); + it('should have valid block times', () => { + for (let i=0; i<10; i++) expect(page.getTimeValidity(i)).toBeTruthy(); }); - it('should contain 10 Blocks Items when the page change', () => { - page.navigateTo(); - expect(page.getPagination()).toBe(true); + it('should have valid block numbers', () => { + for (let i=0; i<10; i++) expect(page.getBlockNumber(i)).toBeGreaterThan(0); + }); + + it('should have valid transaction counts', () => { + for (let i=0; i<10; i++) expect(page.getTransactionCount(i)).toBeGreaterThan(0); + }); + + it('should have valid block hashes', () => { + for (let i=0; i<10; i++) expect(page.getBlockHashLength(i)).toEqual(64); + }); + + it('should contain a pagination control', () => { + expect(page.getIfPaginationControlExists()).toBe(true); + }); + + it('should navigate to the next page and show 10 block items', () => { + let blockCount = page.navigateToTheNextPage().then(() => { + return page.getBlocksListRowCount(); + }); + + expect(blockCount).toEqual(10); + }); + + it('should navigate to the previous page and show 10 block items', () => { + let blockCount = page.navigateToThePreviousPage().then(() => { + return page.getBlocksListRowCount(); + }); + + expect(blockCount).toEqual(10); + }); + + it('should navigate to the last page and show at least 1 block item', () => { + let blockCount = page.navigateToTheLastPage().then(() => { + return page.getBlocksListRowCount(); + }); + + expect(blockCount).toBeGreaterThan(0); + }); + + it('should navigate to the first page and show 10 block items', () => { + let blockCount = page.navigateToTheFirstPage().then(() => { + return page.getBlocksListRowCount(); + }); + + expect(blockCount).toEqual(10); + }); + + it('should navigate to the second page and show 10 block items', () => { + let blockCount = page.pressPageButton(2).then(() => { + return page.getBlocksListRowCount(); + }); + + expect(blockCount).toEqual(10); }); }); \ No newline at end of file diff --git a/e2e/blocks/blocks.po.ts b/e2e/blocks/blocks.po.ts index 90a207ef..95bf6445 100644 --- a/e2e/blocks/blocks.po.ts +++ b/e2e/blocks/blocks.po.ts @@ -1,76 +1,102 @@ import { browser, by, element, protractor } from 'protractor'; export class BlocksPage { - navigateTo() { - return browser.get('/'); - } - - getBlocksText() { - return element(by.css('app-root h2')).getText(); + getPageTitle(titleNumber: number) { + return element + .all(by.css('app-root h2')) + .get(titleNumber) + .getAttribute('textContent'); } getUnconfirmedTransactionsText() { - return element(by.css('.-link')).getText(); + return element.all(by.css('.-link')).get(0).getText(); } getRichListText() { return element.all(by.css('.-link')).get(1).getText(); } - getDetailslabels() { - return element.all(by.css('.-label')); + getStatsLabelsCount() { + return element + .all(by.css('.-label')) + .count(); } - getDetailsLabelsCount() { - return this.getDetailslabels() - .count() - .then(count => { - return count; - }); + getStat(statIndex: number) { + return element + .all(by.css('.-value')) + .get(statIndex) + .getText() + .then(text => Number(text.replace(new RegExp(',', 'g'), ''))); } - getDetailsValues() { - return element.all(by.css('.-value')); + getBlocksList() { + return element.all(by.css('.table a.-row')); } - getDetailsValuesCount() { - return this.getDetailsValues() - .count() - .then(count => { - return count; - }); + getBlocksListRowCount() { + return element + .all(by.css('.table a.-row')) + .count(); } - getBlocksList() { - return element.all(by.css('.table a.-row')); + private getTableCellValue(row: number, column: number) { + return element + .all(by.css('.table a.-row')) + .get(row) + .all(by.css('div')) + .get(column) + .getText(); + } + + getTimeValidity(row: number) { + return this.getTableCellValue(row, 1) + .then(text => !isNaN((new Date(text)).getTime())); + } + + getBlockNumber(row: number) { + return this.getTableCellValue(row, 2) + .then(text => Number(text)); + } + + getTransactionCount(row: number) { + return this.getTableCellValue(row, 3) + .then(text => Number(text)); } - getBlocksListCount() { - return this.getBlocksList() - .count() - .then(count => { - return count; - }); + getBlockHashLength(row: number) { + return this.getTableCellValue(row, 4) + .then(text => text.length); } - getPagination() { + getIfPaginationControlExists() { return element(by.css('.pagination')).isPresent(); } - changePage() { - return element(by.css('.-page')) - .click() - .then(() => { - return this.getBlocksListCount(); - }); + navigateToTheNextPage() { + return element(by.css('.-next')) + .click(); + } + + navigateToThePreviousPage() { + return element(by.css('.-previous')) + .click(); + } + + navigateToTheLastPage() { + return element(by.css('.-last')) + .click(); + } + + navigateToTheFirstPage() { + return element(by.css('.-first')) + .click(); } - putBlockInSearchCmp() { - return element(by.css('.-search-bar-container input')).sendKeys( - 'b54777a8afb5573dec8388a416fa9e6e9eda577a445ff25ef4a2954e1426b817', - protractor.Key.ENTER - ).then(()=>{ - return element(by.css('.element-details-wrapper h2')).getText(); - }) + pressPageButton(index: number) { + return element + .all(by.css('.-page')) + .get(index) + .click(); } } \ No newline at end of file diff --git a/e2e/general.po.ts b/e2e/general.po.ts new file mode 100644 index 00000000..1ae7db59 --- /dev/null +++ b/e2e/general.po.ts @@ -0,0 +1,72 @@ +import { browser, by, element } from 'protractor'; + +export class GeneralPageFunctions { + navigateTo(route: string) { + return browser.get(route); + } + + goBack() { + browser.navigate().back(); + } + + getPageTitle() { + return element(by.css('.element-details-wrapper h2')).getText(); + } + + getDetailsRowCount() { + return element + .all(by.css('.element-details .-row')) + .count() + .then(count => { + return count; + }); + } + + getTransactionId(transsactionIndex: number) { + return element + .all(by.css('.transaction')) + .get(transsactionIndex) + .element(by.css('.-row a')) + .getText(); + } + + getTransactionDateValidity(transsactionIndex: number) { + return element + .all(by.css('.transaction')) + .get(transsactionIndex) + .element(by.css('.-date')) + .getText() + .then(text => !isNaN((new Date(text)).getTime())); + } + + getTransactionInputs(transsactionIndex: number) { + return element + .all(by.css('.transaction')) + .get(transsactionIndex) + .all(by.css('.-data > .row > div:nth-of-type(1) a')) + .map((element, i) => element.getText()) + .then(texts => texts.join(",")); + } + + getTransactionOutputs(transsactionIndex: number) { + return element + .all(by.css('.transaction')) + .get(transsactionIndex) + .all(by.css('.-data > .row > div:nth-of-type(2) a')) + .map((element, i) => element.getText()) + .then(texts => texts.join(",")); + } + + getTransactionInputsAndOutputsTotalCoins() { + return element + .all(by.css('.-balance > div:nth-of-type(2)')) + .map((element, i) => element.getText()) + .then(texts => texts.map(text => Number((text as string).replace(',', ''))).reduce((total, val) => total+val, 0)) + .then(result => Math.round(result * 1000000) / 1000000); + } + + getErrorMessage() { + return element(by.css('div.row.-msg-container > div')) + .getText(); + } +} \ No newline at end of file diff --git a/e2e/navigation/navigation.e2e-spec.ts b/e2e/navigation/navigation.e2e-spec.ts new file mode 100644 index 00000000..8a31e4af --- /dev/null +++ b/e2e/navigation/navigation.e2e-spec.ts @@ -0,0 +1,41 @@ +import { NavigarionPage } from "./navigation.po"; +import { GeneralPageFunctions } from "../general.po"; + +describe('skycoin-explorer Navigation', () => { + const page = new NavigarionPage(); + const generalFunctions = new GeneralPageFunctions(); + + beforeEach(() => { }); + + it('should open the blocks page', () => { + generalFunctions.navigateTo('/'); + }); + + it('should navigate to the richlist page', () => { + page.goToRichlistPage(); + }); + + it('should navigate to the unconfirmed transaction page', () => { + generalFunctions.goBack(); + page.goToUnconfirmedTransactions(); + }); + + it('should navigate to the block details page', () => { + generalFunctions.goBack(); + page.goToBlockDetails(); + }); + + it('should navigate to the transaction detail page', () => { + page.goToTransactionDetail(); + }); + + it('should navigate to the address detail page', () => { + generalFunctions.goBack(); + page.goToAddressDetail(); + }); + + it('should navigate to the unspent outputs page', () => { + page.goToUnspentOutputs(); + }); + +}); \ No newline at end of file diff --git a/e2e/navigation/navigation.po.ts b/e2e/navigation/navigation.po.ts new file mode 100644 index 00000000..55caa31f --- /dev/null +++ b/e2e/navigation/navigation.po.ts @@ -0,0 +1,31 @@ +import { browser, by, element } from 'protractor'; + +export class NavigarionPage { + navigateTo() { + return browser.get('/'); + } + + goToRichlistPage() { + return element.all(by.css('.-link')).get(1).click(); + } + + goToUnconfirmedTransactions() { + return element.all(by.css('.-link')).get(0).click(); + } + + goToBlockDetails() { + return element.all(by.css('.table a.-row')).get(0).click(); + } + + goToTransactionDetail() { + return element(by.css('.transaction .-row a')).click(); + } + + goToAddressDetail() { + return element(by.css('.transaction > .-data > .row > div:nth-of-type(2) a')).click(); + } + + goToUnspentOutputs() { + return element(by.css('.element-details-wrapper .element-details .-link')).click(); + } +} \ No newline at end of file diff --git a/e2e/richlist/richlist.e2e-spec.ts b/e2e/richlist/richlist.e2e-spec.ts index 8e654fe1..60cf1178 100644 --- a/e2e/richlist/richlist.e2e-spec.ts +++ b/e2e/richlist/richlist.e2e-spec.ts @@ -1,18 +1,35 @@ import { RichlistPage } from './richlist.po'; +import { GeneralPageFunctions } from "../general.po"; describe('skycoin-explorer Rich List Page', () => { const page = new RichlistPage(); + const generalFunctions = new GeneralPageFunctions(); beforeEach(() => { }); - - it('should display Rich List text', () => { - page.navigateTo(); - expect(page.getRichlistText()).toEqual('Rich List'); + + it('should display the title', () => { + generalFunctions.navigateTo('/app/richlist'); + expect(page.getPageTitle()).toEqual('Rich List'); }); it('should contain 20 Entries', () => { - page.navigateTo(); - expect(page.getEntriesCount()).toEqual(20); + expect(page.getEntriesCount()).toEqual(20); + }); + + it('should have valid entry numbers', () => { + for (let i=0; i<20; i++) expect(page.getEntryNumber(i)).toBeGreaterThan(0); + }); + + it('should have valid addresses', () => { + for (let i=0; i<20; i++) { + let AddressLength = page.getAddressLength(i); + expect(AddressLength).toBeGreaterThan(26); + expect(AddressLength).toBeLessThan(36); + } + }); + + it('should have valid amounts', () => { + for (let i=0; i<20; i++) expect(page.getAmount(i)).toBeGreaterThan(0); }); }); \ No newline at end of file diff --git a/e2e/richlist/richlist.po.ts b/e2e/richlist/richlist.po.ts index a9a8d018..4e58cb21 100644 --- a/e2e/richlist/richlist.po.ts +++ b/e2e/richlist/richlist.po.ts @@ -1,31 +1,39 @@ import { browser, by, element, protractor } from 'protractor'; export class RichlistPage { - navigateTo() { - return browser.get('/'); + getPageTitle() { + return element + .all(by.css('app-root h2')) + .get(0) + .getAttribute('textContent'); } - goToRichlist() { - return element.all(by.css('.-link')).get(1).click(); + getEntriesCount() { + return element.all(by.css('.table a.-row')) + .count(); } - getRichlistText() { - return this.goToRichlist().then(() => { - return element(by.css('app-root h2')).getText(); - }); + private getTableCellValue(row: number, column: number) { + return element + .all(by.css('.table a.-row')) + .get(row) + .all(by.css('div')) + .get(column) + .getText(); } - getEntriesList() { - return element.all(by.css('.table a.-row')); + getEntryNumber(row: number) { + return this.getTableCellValue(row, 1) + .then(text => Number(text)); } - getEntriesCount() { - return this.goToRichlist().then(() => { - return this.getEntriesList() - .count() - .then(count => { - return count; - }); - }); + getAddressLength(row: number) { + return this.getTableCellValue(row, 2) + .then(text => text.length); + } + + getAmount(row: number) { + return this.getTableCellValue(row, 3) + .then(text => Number(text.split(' ')[0].replace(new RegExp(',', 'g'), ''))); } } \ No newline at end of file diff --git a/e2e/search/search.e2e-spec.ts b/e2e/search/search.e2e-spec.ts index 2d0c3223..8c9dc1f8 100644 --- a/e2e/search/search.e2e-spec.ts +++ b/e2e/search/search.e2e-spec.ts @@ -1,13 +1,35 @@ -import { BlocksPage } from '../blocks/blocks.po'; +import { SearchPage } from "./search.po"; +import { GeneralPageFunctions } from "../general.po"; describe('skycoin-explorer Search Component', () => { - const page = new BlocksPage(); + const page = new SearchPage(); + const generalFunctions = new GeneralPageFunctions(); beforeEach(() => { }); - it('should write one block inside search component', () => { - page.navigateTo(); - expect(page.putBlockInSearchCmp()).toEqual('Block Details'); + it('should find a block by hash', () => { + generalFunctions.navigateTo('/'); + page.search('114fe60587a158428a47e0f9571d764f495912c299aa4e67fc88004cf21b0c24').then(()=>{ + expect(generalFunctions.getPageTitle()).toEqual('Block Details'); + }); + }); + + it('should find a transaction by hash', () => { + page.search('0579e7727627cd9815a8a8b5e1df86124f45a4132cc0dbd00d2f110e4f409b69').then(()=>{ + expect(generalFunctions.getPageTitle()).toEqual('Transaction'); + }); + }); + + it('should find a block by number', () => { + page.search('5').then(()=>{ + expect(generalFunctions.getPageTitle()).toEqual('Block Details'); + }); + }); + + it('should find an address', () => { + page.search('24ooGeabUGQLnJmoyviqA8h2y7Cgz2CY4x7').then(()=>{ + expect(generalFunctions.getPageTitle()).toEqual('24ooGeabUGQLnJmoyviqA8h2y7Cgz2CY4x7'); + }); }); }); \ No newline at end of file diff --git a/e2e/search/search.po.ts b/e2e/search/search.po.ts new file mode 100644 index 00000000..57dcc567 --- /dev/null +++ b/e2e/search/search.po.ts @@ -0,0 +1,10 @@ +import { browser, by, element, protractor } from 'protractor'; + +export class SearchPage { + search(text: string) { + return element(by.css('.-search-bar-container input')).sendKeys( + text, + protractor.Key.ENTER + ); + } +} \ No newline at end of file diff --git a/e2e/transaction-detail/transaction-detail.e2e-spec.ts b/e2e/transaction-detail/transaction-detail.e2e-spec.ts index 5cd18a27..f9d3ea8b 100644 --- a/e2e/transaction-detail/transaction-detail.e2e-spec.ts +++ b/e2e/transaction-detail/transaction-detail.e2e-spec.ts @@ -1,36 +1,55 @@ import { TransactionDetailPage } from './transaction-detail.po'; +import { GeneralPageFunctions } from "../general.po"; describe('skycoin-explorer Transaction Page', () => { const page = new TransactionDetailPage(); + const generalFunctions = new GeneralPageFunctions(); beforeEach(() => { }); - it('should display Transaction text', () => { - page.navigateTo(); - expect(page.getTransactionText()).toEqual('Transaction'); + it('should display the title', () => { + generalFunctions.navigateTo('/app/transaction/0579e7727627cd9815a8a8b5e1df86124f45a4132cc0dbd00d2f110e4f409b69'); + expect(generalFunctions.getPageTitle()).toBe("Transaction"); }); - it('should display 4 Transaction details Rows', () => { - page.navigateTo(); - expect(page.getDetailsRow()).toEqual(4); + it('should display 4 transaction details rows', () => { + expect(generalFunctions.getDetailsRowCount()).toEqual(4); }); - it('should show the Transaction Id and its length should be 64', () => { - page.navigateTo(); - expect(page.getTransactionId()).toEqual(64); + it('should show a valid timestamp', () => { + expect(page.getTimestampValidity()).toBeTruthy(); }); - it('should show One of Transaction Input and its length should be l>26 and l<36', () => { - page.navigateTo(); - let inputAddress = page.getOneTransactionInput(); - expect(inputAddress).toBeLessThan(36); - expect(inputAddress).toBeGreaterThan(26); + it('should show the correct size', () => { + expect(page.getSize()).toBe(317); }); - it('should show One of Transaction Output and its length should be l>26 and l<36', () => { - page.navigateTo(); - let outputAddress = page.getOneTransactionOutput(); - expect(outputAddress).toBeLessThan(36); - expect(outputAddress).toBeGreaterThan(26); + it('should show the correct block number', () => { + expect(page.getBlockNumber()).toBe(5); + }); + + it('should show the correct transaction ID', () => { + expect(generalFunctions.getTransactionId(0)).toEqual('0579e7727627cd9815a8a8b5e1df86124f45a4132cc0dbd00d2f110e4f409b69'); + }); + + it('should show a valid transaction date', () => { + expect(generalFunctions.getTransactionDateValidity(0)).toBeTruthy(); + }); + + it('should show the correct transaction inputs', () => { + expect(generalFunctions.getTransactionInputs(0)).toBe('R6aHqKWSQfvpdo2fGSrq4F1RYXkBWR9HHJ,R6aHqKWSQfvpdo2fGSrq4F1RYXkBWR9HHJ'); + }); + + it('should show the correct transaction outputs', () => { + expect(generalFunctions.getTransactionOutputs(0)).toBe('R6aHqKWSQfvpdo2fGSrq4F1RYXkBWR9HHJ,2fGC7kwAM9yZyEF1QqBqp8uo9RUsF6ENGJF'); + }); + + it('should have the correct coins amount', () => { + expect(generalFunctions.getTransactionInputsAndOutputsTotalCoins()).toBe(1999980); + }); + + it('should show the error message', () => { + generalFunctions.navigateTo('/app/transaction/0579e7727627cd9815a8a8b5e1df86124f45a4132cc0dbd00d2f110e4f409b68'); + expect(generalFunctions.getErrorMessage()).toBeDefined(); }); }); \ No newline at end of file diff --git a/e2e/transaction-detail/transaction-detail.po.ts b/e2e/transaction-detail/transaction-detail.po.ts index bbdcfedd..77a7589a 100644 --- a/e2e/transaction-detail/transaction-detail.po.ts +++ b/e2e/transaction-detail/transaction-detail.po.ts @@ -1,60 +1,21 @@ import { browser, by, element } from 'protractor'; export class TransactionDetailPage { - navigateTo() { - return browser.get('/'); + getTimestampValidity() { + return element(by.css('.element-details > div:nth-of-type(2) > div')) + .getText() + .then(text => !isNaN((new Date(text)).getTime())); } - goToTransactionPage() { - return element(by.css('.table a.-row')) - .click() - .then(() => { - return element(by.css('.transaction .-row a')).click(); - }); + getSize() { + return element(by.css('.element-details > div:nth-of-type(3) > div')) + .getText() + .then(text => Number(text.split(' ')[0])); } - getTransactionText() { - return this.goToTransactionPage().then(() => { - return element(by.css('.element-details-wrapper h2')).getText(); - }); - } - - getTransactionId() { - return this.goToTransactionPage().then(() => { - return element(by.css('.transaction .-row a')) - .getText() - .then(text => text.length); - }); - } - - getDetailsRow() { - return this.goToTransactionPage().then(() => { - return element - .all(by.css('.element-details .-row')) - .count() - .then(count => { - return count; - }); - }); - } - - getOneTransactionInput() { - return this.goToTransactionPage().then(() => { - return element - .all(by.css('.transaction > .-data > .row > div:nth-of-type(1) a')) - .get(0) - .getText() - .then(text => text.length); - }); - } - - getOneTransactionOutput() { - return this.goToTransactionPage().then(() => { - return element - .all(by.css('.transaction > .-data > .row > div:nth-of-type(2) a')) - .get(0) - .getText() - .then(text => text.length); - }); + getBlockNumber() { + return element(by.css('.element-details > div:nth-of-type(4) > div')) + .getText() + .then(text => Number(text.replace(new RegExp(',', 'g'), ''))); } } \ No newline at end of file diff --git a/e2e/unconfirmed-transactions/unconfirmed-transactions.e2e-spec.ts b/e2e/unconfirmed-transactions/unconfirmed-transactions.e2e-spec.ts index 41a7cd02..1b7b378f 100644 --- a/e2e/unconfirmed-transactions/unconfirmed-transactions.e2e-spec.ts +++ b/e2e/unconfirmed-transactions/unconfirmed-transactions.e2e-spec.ts @@ -1,19 +1,18 @@ import { UnconfirmedTransactionsPage } from './unconfirmed-transactions.po'; +import { GeneralPageFunctions } from "../general.po"; describe('skycoin-explorer Unconfirmed Transactions Page', () => { const page = new UnconfirmedTransactionsPage(); + const generalFunctions = new GeneralPageFunctions(); beforeEach(() => { }); it('should display Unconfirmed Transactions text', () => { - page.navigateTo(); - expect(page.getUnconfirmedTransactionsText()).toEqual( - 'Unconfirmed Transactions' - ); + generalFunctions.navigateTo('/app/unconfirmedtransactions'); + expect(generalFunctions.getPageTitle()).toEqual('Unconfirmed Transactions'); }); it('should display 4 Unconfirmed Transactions details', () => { - page.navigateTo(); - expect(page.getDetailsRow()).toEqual(4); + expect(generalFunctions.getDetailsRowCount()).toEqual(4); }); }); \ No newline at end of file diff --git a/e2e/unconfirmed-transactions/unconfirmed-transactions.po.ts b/e2e/unconfirmed-transactions/unconfirmed-transactions.po.ts index dbef9b10..78e07508 100644 --- a/e2e/unconfirmed-transactions/unconfirmed-transactions.po.ts +++ b/e2e/unconfirmed-transactions/unconfirmed-transactions.po.ts @@ -1,28 +1,5 @@ import { browser, by, element } from 'protractor'; export class UnconfirmedTransactionsPage { - navigateTo() { - return browser.get('/'); - } - - goToUnconfirmedTransactions() { - return element(by.css('.-link')).click(); - } - - getUnconfirmedTransactionsText() { - return this.goToUnconfirmedTransactions().then(() => { - return element(by.css('app-root h2')).getText(); - }); - } - - getDetailsRow() { - return this.goToUnconfirmedTransactions().then(() => { - return element - .all(by.css('.-row')) - .count() - .then(count => { - return count; - }); - }); - } + } \ No newline at end of file diff --git a/e2e/unspent-outputs/unspent-outputs.e2e-spec.ts b/e2e/unspent-outputs/unspent-outputs.e2e-spec.ts index 62f16f53..2c93e39a 100644 --- a/e2e/unspent-outputs/unspent-outputs.e2e-spec.ts +++ b/e2e/unspent-outputs/unspent-outputs.e2e-spec.ts @@ -1,40 +1,51 @@ import { UnspentOutputsPage } from "./unspent-outputs.po"; +import { GeneralPageFunctions } from "../general.po"; describe('skycoin-explorer Unspent Outputs Page', () => { const page = new UnspentOutputsPage(); + const generalFunctions = new GeneralPageFunctions(); beforeEach(() => { }); - it('should display Unspent Outputs text', () => { - page.navigateTo(); - expect(page.getUnspentOutputsText()).toEqual('Unspent Outputs'); + it('should display the title', () => { + generalFunctions.navigateTo('/app/unspent/24ooGeabUGQLnJmoyviqA8h2y7Cgz2CY4x7'); + expect(generalFunctions.getPageTitle()).toBe("Unspent Outputs"); }); - it('should show the Address Text and its length should be l>26 and l<36', () => { - page.navigateTo(); - let address = page.getAddressText(); - expect(address).toBeLessThan(36); - expect(address).toBeGreaterThan(26); + it('should display 3 details rows', () => { + expect(generalFunctions.getDetailsRowCount()).toEqual(3); }); - it('should show the Outputs Info row and its length should be 3', () => { - page.navigateTo(); - expect(page.getOutputsInfo()).toEqual(3); + it('should show the correct address', () => { + expect(page.getAddressText()).toBe("24ooGeabUGQLnJmoyviqA8h2y7Cgz2CY4x7"); }); - it('should show the Outputs Rows and its length should be more than 0', () => { - page.navigateTo(); - expect(page.getOutputs()).toBe(true); + it('should show the correct number of outputs', () => { + expect(page.getNumberOfOutputs()).toBe(1); }); - it('should show One Transaction Id and its length should be 64', () => { - page.navigateTo(); - expect(page.getOneTransactionId()).toEqual(64); + it('should show the correct number of coins', () => { + expect(page.getTotalCoins()).toBe(0.001); }); - it('should show One Output Id and its length should be 64', () => { - page.navigateTo(); - expect(page.getOneOutputId()).toEqual(64); + it('should show the correct origin transaction ID', () => { + expect(generalFunctions.getTransactionId(0)).toEqual('f375dfb0cea3f082daa03341f6283a483a9857206442feabc94f2b05b1df1fab'); }); + it('should show a valid transaction date', () => { + expect(generalFunctions.getTransactionDateValidity(0)).toBeTruthy(); + }); + + it('should show the correct output hash', () => { + expect(page.getOutputId(0)).toBe('74ef6da8c13ec55f28a99aab6bcf890b8decea8c7c56ed55f0b9b4b8cef069da'); + }); + + it('should have the correct coins amount', () => { + expect(generalFunctions.getTransactionInputsAndOutputsTotalCoins()).toBe(0.001); + }); + + it('should show the error message', () => { + generalFunctions.navigateTo('/app/unspent/24ooGeabUGQLnJmoyviqA8h2y7Cgz2CY4x8'); + expect(generalFunctions.getErrorMessage()).toBeDefined(); + }); }); \ No newline at end of file diff --git a/e2e/unspent-outputs/unspent-outputs.po.ts b/e2e/unspent-outputs/unspent-outputs.po.ts index b59fe4fd..ef12b695 100644 --- a/e2e/unspent-outputs/unspent-outputs.po.ts +++ b/e2e/unspent-outputs/unspent-outputs.po.ts @@ -1,72 +1,29 @@ import { browser, by, element } from 'protractor'; export class UnspentOutputsPage { - navigateTo() { - return browser.get('/'); - } - - goToUnspentOutputsPage() { - return element(by.css('.table a.-row')) - .click() - .then(() => { - return element(by.css('.transaction > .-data > .row > div:nth-of-type(2) a')) - .click().then(() => { - return element(by.css('.element-details-wrapper .element-details .-link')) - .click(); - }); - }); - } - - getUnspentOutputsText() { - return this.goToUnspentOutputsPage().then(() => { - return element(by.css('.element-details-wrapper h2')) - .getText(); - }); - } getAddressText() { - return this.goToUnspentOutputsPage().then(() => { - return element(by.css('.element-details-wrapper .element-details .-link')) - .getText() - .then(text => text.length); - }); - } - - getOutputsInfo() { - return this.goToUnspentOutputsPage().then(() => { - return element - .all(by.css('.element-details > div')) - .count() - .then(count => count); - }); + return element(by.css('.element-details-wrapper .element-details .-link')) + .getText(); } - getOutputs() { - return this.goToUnspentOutputsPage().then(() => { - return element - .all(by.css('.transaction')) - .count() - .then(count => count > 0); - }); + getNumberOfOutputs() { + return element(by.css('.element-details > div:nth-of-type(2) > div')) + .getText() + .then(text => Number(text)); } - getOneTransactionId() { - return this.goToUnspentOutputsPage().then(() => { - return element - .all(by.css('.transaction .-title a')) - .get(0) - .getText() - .then(text => text.length); - }); + getTotalCoins() { + return element(by.css('.element-details > div:nth-of-type(3) > div')) + .getText() + .then(text => Number(text.split(' ')[0].replace(new RegExp(',', 'g'), ''))); } - getOneOutputId() { - return this.goToUnspentOutputsPage().then(() => { - return element - .all(by.css('.transaction > .-data > .row .-body div')) - .get(0) - .getText() - .then(text => text.length); - }); + getOutputId(outputIndex: number) { + return element + .all(by.css('.transaction')) + .get(outputIndex) + .element(by.css('.-data > .row .-body div')) + .getText(); } } \ No newline at end of file diff --git a/src/app/components/pages/address-detail/address-detail.component.html b/src/app/components/pages/address-detail/address-detail.component.html index a0b16568..c19d4665 100644 --- a/src/app/components/pages/address-detail/address-detail.component.html +++ b/src/app/components/pages/address-detail/address-detail.component.html @@ -4,7 +4,7 @@

{{ 'addressDetail.title' | translate }}

- {{ 'general.address' | translate }}
{{ address ? address : loadingMsg }} + {{ 'general.address' | translate }}
{{ address ? address : loadingMsg }}
{{ 'addressDetail.txsNumber' | translate }}
{{ transactions ? transactions.length : loadingMsg }}
{{ 'addressDetail.totalReceived' | translate }}
{{ transactions ? ( totalReceived | number:'1.0-6') : loadingMsg }}