Skip to content

Commit

Permalink
test: Add dashboard content check and search epochs and blocks tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Luis Zarate committed May 6, 2024
1 parent f739924 commit e617b9f
Show file tree
Hide file tree
Showing 12 changed files with 284 additions and 34 deletions.
2 changes: 1 addition & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default defineConfig({
/* Maximum time one test can run for. */
timeout: 30 * 1000,
expect: {
timeout: 10000
timeout: 20000
},
/* Run tests in files in parallel */
fullyParallel: false,
Expand Down
34 changes: 33 additions & 1 deletion playwright/api/call-blockfrost/blockfrost.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,40 @@ export function blockfrostApi(request: APIRequestContext) {
);
};

const getEpochById = async (epochId: number) => {
return BaseApi.getData(
request,
Endpoint.BlockFrost.GetEpochById.Base + `/${epochId}`,
{},
{
Accept: "*/*",
"Accept-Encoding": "gzip, deflate, br",
"Content-Type": "application/json",
project_id: BLOCKFROST_TOKEN
},
false
);
};

const getBlockByNumber = async (blockNumber: number) => {
return BaseApi.getData(
request,
Endpoint.BlockFrost.GetBlockByNumber.Base + `/${blockNumber}`,
{},
{
Accept: "*/*",
"Accept-Encoding": "gzip, deflate, br",
"Content-Type": "application/json",
project_id: BLOCKFROST_TOKEN
},
false
);
};

return {
getLastEpochData,
getLatestBlockData
getLatestBlockData,
getEpochById,
getBlockByNumber
};
}
18 changes: 17 additions & 1 deletion playwright/api/call-blockfrost/blockfrost.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,25 @@ export async function blockfrostService(request: APIRequestContext) {
return finishedEpochId - 1;
};

const getEpochById = async (epochId: number) => {
const epochResponse = await blockfrostApi(request).getEpochById(epochId);
expect(epochResponse.status()).toEqual(HttpStatusCode.Ok);
const epochData: BlockfrostEpochInformationDto = await epochResponse.json();
return epochData;
};

const getBlockByNumber = async (blockNumber: number) => {
const blockResponse = await blockfrostApi(request).getBlockByNumber(blockNumber);
expect(blockResponse.status()).toEqual(HttpStatusCode.Ok);
const blockData: BlockInformationDto = await blockResponse.json();
return blockData;
};

return {
getLastBlockData,
getLastEpochData,
getLastFinishedEpochId
getLastFinishedEpochId,
getEpochById,
getBlockByNumber
};
}
10 changes: 10 additions & 0 deletions playwright/helpers/SearchFilters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export enum SearchFilters {
Epochs = "Epochs",
Blocks = "Blocks",
Transactions = "Transactions",
AdaHandle = "ADA Handle",
Tokens = "Tokens",
Addresses = "Addresses",
Pools = "Pools",
ScriptHash = "Script Hash"
}
11 changes: 11 additions & 0 deletions playwright/helpers/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ export class BlockFrost {
return `${BlockFrost.BASE_MAIN_NET_URL}/epochs/latest`;
}
};
static GetEpochById = class {
public static get Base() {
return `${BlockFrost.BASE_MAIN_NET_URL}/epochs`;
}
};

static GetBlockByNumber = class {
public static get Base() {
return `${BlockFrost.BASE_MAIN_NET_URL}/blocks`;
}
};
}

export class Koios {
Expand Down
34 changes: 27 additions & 7 deletions playwright/pages/block-detail.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,36 @@ export function blockDetailPage(page: Page) {
const blockNumber = page.locator('//div[div[div[text()="Block"]]]/following-sibling::div');
const blockTotalOutput = page.locator('//div[div[div[text()="Total output in ADA"]]]/following-sibling::div');
const assertBlockDataIsDisplayed = async (lastBlockDataApi: Promise<BlockInformationDto>) => {
await expect(blockId).toHaveText((await lastBlockDataApi).hash);
await expect(blockId, "The block id is not the expected for the current block details").toHaveText(
(
await lastBlockDataApi
).hash
);
const convertedTime = Methods().getTimeAndDateFromEpoch((await lastBlockDataApi).time);
await expect(blockCreateAt).toHaveText(await convertedTime);
await expect(blockTransactionsCount).toHaveText((await lastBlockDataApi).tx_count.toString());
await expect(epochNumber).toHaveText((await lastBlockDataApi).epoch.toString());
const expectedTime = await blockCreateAt.textContent();
expect(
expectedTime?.replace(",", ""),
"The block created date is not the expected for the current block details"
).toEqual(await convertedTime);
await expect(
blockTransactionsCount,
"The block transactions count is not the expected for the current block details"
).toHaveText((await lastBlockDataApi).tx_count.toString());
await expect(epochNumber, "The block's epoch number is not the expected for the current block details").toHaveText(
(await lastBlockDataApi).epoch.toString()
);
const fullSlotData = (await lastBlockDataApi).epoch_slot + " - " + (await lastBlockDataApi).slot;
await expect(blockSlotData).toHaveText(fullSlotData);
await expect(blockNumber).toHaveText((await lastBlockDataApi).height.toString());
await expect(blockSlotData, "The slot data is not is not the expected for the current block details").toHaveText(
fullSlotData
);
await expect(blockNumber, "The block number is not is not the expected for the current block details").toHaveText(
(await lastBlockDataApi).height.toString()
);
const totalOutput = await blockTotalOutput.textContent();
expect((await lastBlockDataApi).output.replace(/0$/, "")).toEqual(totalOutput?.replace(/[,.]/g, "").trim());
expect(
(await lastBlockDataApi).output.replace(/0$/, ""),
"The block's total output is not the expected for the current block details"
).toEqual(totalOutput?.replace(/[,.]/g, "").trim());
};
return {
assertBlockDataIsDisplayed
Expand Down
55 changes: 48 additions & 7 deletions playwright/pages/dashboard.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ export function dashboard(page: Page) {
const blockchainMenu = page.getByTestId("menu-button-blockchain");
const blocksSection = page.getByTestId("submenu-button-blocks");
const epochsSection = page.getByTestId("submenu-button-epochs");
const transactionChart = page.getByTestId("home-trending");
const poolsSection = page.getByTestId("home-top-delegation");
const latestStories = page.getByTestId("home-latest-stories");
const searchBar = page.locator('div[data-testid="search-bar"] input');
const searchButton = page.locator('div[data-testid="search-bar"] + button[type="submit"]');
const searchFilters = page.getByTestId("all-filters-dropdown");
const filterOptions = page.getByTestId("filter-options");
const goTo = async () => {
await page.goto("/");
};
Expand All @@ -25,22 +32,56 @@ export function dashboard(page: Page) {
await epochsSection.click();
};

const assertItLoads = async () => {
const assertDashboardInfoCards = async () => {
await assert(page).pageTitle("Cardano Blockchain Explorer");
await expect(adaPriceBox).toBeVisible();
await expect(marketCap).toBeVisible();
await expect(epochBox).toBeVisible();
await expect(liveStakeBox).toBeVisible();
await expect(adaPriceBox, "Info card with current Ada price should be visible").toBeVisible();
await expect(marketCap, "Info card with market cap should be visible").toBeVisible();
await expect(epochBox, "Info card with current epoch info should be displayed").toBeVisible();
await expect(liveStakeBox, "Info card with current Live stake progression data should be displayed").toBeVisible();
};

const assertTransactionsInfoSections = async () => {
await expect(transactionChart, "Dashboard page should show a transaction chart of the last 24H").toBeVisible();
const lastTransactionsCards = page.locator('div[class="MuiBox-root css-iqjs4s"]').all();
expect(
(await lastTransactionsCards).length.valueOf(),
"4 Info cards with the last transactions data should be visible"
).toEqual(4);
};

const assertPoolsInfoSection = async () => {
await expect(poolsSection, "Dashboard page should show a table with the last 5 most saturated pools").toBeVisible();
};
const assertLatestStoriesSection = async () => {
await expect(
latestStories,
"Dashboard page should show a section with the latest stories from Cardano Foundation"
).toBeVisible();
};

const assertUserLoggedIn = async (userAccount: string) => {
const userAccountName = await accountButton.textContent();
expect(userAccount).toContain(userAccountName?.trim());
expect(userAccount, "User should see his user name in account button").toContain(userAccountName?.trim());
};
const applyFilterToSearchBar = async (filterName: string) => {
await searchFilters.click();
await filterOptions.filter({ hasText: filterName }).click();
};

const searchFor = async (searchInput: string) => {
await searchBar.fill(searchInput);
await searchButton.click();
await new Promise((f) => setTimeout(f, 10000));
};

return {
assertUserLoggedIn,
assertItLoads,
assertDashboardInfoCards,
assertTransactionsInfoSections,
assertPoolsInfoSection,
assertLatestStoriesSection,
applyFilterToSearchBar,
searchFor,
openBlocksSection,
openEpochsSection,
goTo
Expand Down
68 changes: 53 additions & 15 deletions playwright/pages/epoch-detail.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,50 +7,88 @@ import { log } from "../utils/logger";

export function epochDetailPage(page: Page) {
const epochId = page.locator('div[data-test-id="CircularProgressbarWithChildren__children"] > a');
const epochStartTime = page.locator('//div[div[div[text()="Start timestamp"]]]/following-sibling::div');
const epochStartTime = page.locator(
"//div[div[div[@data-testid='epoch.overview.startTimeTitle']]]/following-sibling::div"
);
const epochEndTime = page.locator('//div[div[div[text()="End timestamp"]]]/following-sibling::div');
const totalOutput = page.locator('//div[div[div[text()="Total output"]]]/following-sibling::div');
const blocksCount = page.locator('//div[div[div[text()="Blocks"]]]/following-sibling::div');
const transactionCount = page.locator('//div[div[div[text()="Transaction Count"]]]/following-sibling::div');

const assertLastActiveEpochDataIsDisplayed = async (lastEpochData: Promise<BlockfrostEpochInformationDto>) => {
await expect(epochId).toHaveText((await lastEpochData).epoch.toString());
const assertEpochDataIsDisplayed = async (lastEpochData: Promise<BlockfrostEpochInformationDto>) => {
await expect(epochId, "The epoch id is not the expected for the current epoch details").toHaveText(
(await lastEpochData).epoch.toString()
);
const startTime = getFormattedTime((await lastEpochData).start_time);
await expect(epochStartTime).toHaveText(await startTime);
const expectedStartTime = await epochStartTime.textContent();
expect(
expectedStartTime?.replace(",", ""),
"The epoch start time is not the expected for the current epoch details"
).toEqual(await startTime);
const endTime = getFormattedTime((await lastEpochData).end_time);
await expect(epochEndTime).toHaveText(await endTime);
const expectedEndTime = await epochEndTime.textContent();
expect(
expectedEndTime?.replace(",", ""),
"The epoch end time is not the expected for the current epoch details"
).toEqual(await endTime);
const receivedOutput = Methods().getNumberFromStringWithNDecimals((await lastEpochData).output, 6);
const currentOutput = parseFloat(<string>(await totalOutput.textContent())?.replace(/,/g, ""));
expect(currentOutput).toBeGreaterThanOrEqual(await receivedOutput);
expect(
currentOutput,
"The epoch's current output is not the expected for the current epoch details"
).toBeGreaterThanOrEqual(await receivedOutput);
const currentBlocksCount = parseInt(<string>await blocksCount.textContent());
expect(currentBlocksCount).toBeGreaterThanOrEqual((await lastEpochData).block_count);
expect(
currentBlocksCount,
"The epoch's blocks count is not the expected for the current epoch details"
).toBeGreaterThanOrEqual((await lastEpochData).block_count);
const currentTransactionsCount = parseInt(<string>await transactionCount.textContent());
expect(currentTransactionsCount).toBeGreaterThanOrEqual((await lastEpochData).tx_count);
expect(
currentTransactionsCount,
"The epoch's transactions count is not the expected for the current epoch details"
).toBeGreaterThanOrEqual((await lastEpochData).tx_count);
};

const assertLastFinishedEpochDataIsDisplayed = async (lastEpochResponse: Promise<KoiosEpochInformationDto[]>) => {
const lastEpochData = (await lastEpochResponse).at(0);
if (lastEpochData !== undefined) {
await expect(epochId).toHaveText(lastEpochData.epoch_no.toString());
await expect(epochId, "The epoch id is not the expected for the current epoch details").toHaveText(
lastEpochData.epoch_no.toString()
);
const startTime = getFormattedTime(lastEpochData.start_time);
await expect(epochStartTime).toHaveText(await startTime);
const expectedStartTime = await epochStartTime.textContent();
expect(
expectedStartTime?.replace(",", ""),
"The epoch start time is not the expected for the current epoch details"
).toEqual(await startTime);
const endTime = getFormattedTime(lastEpochData.end_time);
await expect(epochEndTime).toHaveText(await endTime);
const expectedEndTime = await epochEndTime.textContent();
expect(
expectedEndTime?.replace(",", ""),
"The epoch end time is not the expected for the current epoch details"
).toEqual(await endTime);
const receivedOutput = Methods().getNumberFromStringWithNDecimals(lastEpochData.out_sum, 6);
const currentOutput = parseFloat(<string>(await totalOutput.textContent())?.replace(/,/g, ""));
expect(currentOutput).toEqual(await receivedOutput);
expect(currentOutput, "The epoch's current output is not the expected for the current epoch details").toEqual(
await receivedOutput
);
const currentBlocksCount = parseInt(<string>await blocksCount.textContent());
expect(currentBlocksCount).toEqual(lastEpochData.blk_count);
expect(currentBlocksCount, "The epoch's blocks count is not the expected for the current epoch details").toEqual(
lastEpochData.blk_count
);
const currentTransactionsCount = parseInt(<string>await transactionCount.textContent());
expect(currentTransactionsCount).toEqual(lastEpochData.tx_count);
expect(
currentTransactionsCount,
"The epoch's transactions count is not the expected for the current epoch details"
).toEqual(lastEpochData.tx_count);
} else log.error("Last epoch data object is undefined");
};
const getFormattedTime = async (time: number) => {
return Methods().getTimeAndDateFromEpoch(time);
};

return {
assertLastActiveEpochDataIsDisplayed,
assertEpochDataIsDisplayed,
assertLastFinishedEpochDataIsDisplayed
};
}
25 changes: 25 additions & 0 deletions playwright/tests/e2e/features/dashboard.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Feature: Check explorer dashboard shows a general and updated data of the cardano blockchain

Scenario: Check Explorer dashboard have all the elements with a general resume about explorer content
Given User goes to explorer portal
Then the user should see tha general dashboard page with all the resume information

Scenario: Search for epoch by epoch number using epochs filter
Given User goes to explorer portal
And the user selects the epochs filter in the search bar
And epoch information has been requested through api service
When the user search by the epoch number
Then the user should be redirected to the searched epoch detail view

Scenario: Search by block number using block filter
Given User goes to explorer portal
And the user selects the blocks filter in the search bar
And a block information has been requested through api service
When the user search by the block number
Then the user should be redirected to the searched block detail view

Scenario: Search by block id/hash
Given User goes to explorer portal
And a block information has been requested through api service
When the user search by block id/hash
Then the user should be redirected to the searched block detail view

0 comments on commit e617b9f

Please sign in to comment.