Skip to content

Commit

Permalink
Mobile VRTs (actualbudget#3506)
Browse files Browse the repository at this point in the history
* More Mobile VRTs

* Mobile VRTs

* Fix mobile budget page

* Updated VRT

* VRT fix

* Update VRT

* [skip ci] Release notes

* Cleanup tests

* Fix VRT

* VRT

* Extend timeout

* Clean screenshots

* Updated VRT

* Category / group VRTs

* Mobile budget page menu VRT

* Updated VRT

* Prevous and next budget month tests

* Code Rabbit suggestions

* Feedback

* VRT

* Fix getSelectedMonth

* Fix selectedBudgetMonthButton locator

* Fix flaky tests

* Update VRT
  • Loading branch information
joel-jeremy authored Oct 4, 2024
1 parent 365da79 commit a28fb93
Show file tree
Hide file tree
Showing 154 changed files with 751 additions and 95 deletions.
57 changes: 57 additions & 0 deletions packages/desktop-client/e2e/accounts.mobile.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { test, expect } from '@playwright/test';

import { ConfigurationPage } from './page-models/configuration-page';
import { MobileNavigation } from './page-models/mobile-navigation';

test.describe('Mobile Accounts', () => {
let page;
let navigation;
let configurationPage;

test.beforeEach(async ({ browser }) => {
page = await browser.newPage();
navigation = new MobileNavigation(page);
configurationPage = new ConfigurationPage(page);

await page.setViewportSize({
width: 350,
height: 600,
});
await page.goto('/');
await configurationPage.createTestFile();
});

test.afterEach(async () => {
await page.close();
});

test('opens the accounts page and asserts on balances', async () => {
const accountsPage = await navigation.goToAccountsPage();

const account = await accountsPage.getNthAccount(1);

await expect(account.name).toHaveText('Ally Savings');
await expect(account.balance).toHaveText('7,653.00');
await expect(page).toMatchThemeScreenshots();
});

test('opens individual account page and checks that filtering is working', async () => {
const accountsPage = await navigation.goToAccountsPage();
const accountPage = await accountsPage.openNthAccount(0);

await expect(accountPage.heading).toHaveText('Bank of America');
await expect(accountPage.transactionList).toBeVisible();
await expect(await accountPage.getBalance()).toBeGreaterThan(0);
await expect(accountPage.noTransactionsMessage).not.toBeVisible();
await expect(page).toMatchThemeScreenshots();

await accountPage.searchByText('nothing should be found');
await expect(accountPage.noTransactionsMessage).toBeVisible();
await expect(accountPage.transactions).toHaveCount(0);
await expect(page).toMatchThemeScreenshots();

await accountPage.searchByText('Kroger');
await expect(accountPage.transactions).not.toHaveCount(0);
await expect(page).toMatchThemeScreenshots();
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
281 changes: 281 additions & 0 deletions packages/desktop-client/e2e/budget.mobile.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
import { test, expect } from '@playwright/test';

import * as monthUtils from 'loot-core/src/shared/months';

import { ConfigurationPage } from './page-models/configuration-page';
import { MobileNavigation } from './page-models/mobile-navigation';

const budgetTypes = ['Envelope', 'Tracking'];

budgetTypes.forEach(budgetType => {
test.describe(`Mobile Budget [${budgetType}]`, () => {
let page;
let navigation;
let configurationPage;
let previousGlobalIsTesting;

test.beforeAll(() => {
// TODO: Hack, properly mock the currentMonth function
previousGlobalIsTesting = global.IS_TESTING;
global.IS_TESTING = true;
});

test.afterAll(() => {
// TODO: Hack, properly mock the currentMonth function
global.IS_TESTING = previousGlobalIsTesting;
});

test.beforeEach(async ({ browser }) => {
page = await browser.newPage();
navigation = new MobileNavigation(page);
configurationPage = new ConfigurationPage(page);

await page.setViewportSize({
width: 350,
height: 600,
});
await page.goto('/');
await configurationPage.createTestFile();

if (budgetType === 'Tracking') {
// Set budget type to tracking
const settingsPage = await navigation.goToSettingsPage();
await settingsPage.useBudgetType('tracking');
}
});

test.afterEach(async () => {
await page.close();
});

test('loads the budget page with budgeted amounts', async () => {
const budgetPage = await navigation.goToBudgetPage();
await budgetPage.waitForBudgetTable();

await expect(budgetPage.categoryNames).toHaveText([
'Food',
'Restaurants',
'Entertainment',
'Clothing',
'General',
'Gift',
'Medical',
'Savings',
'Cell',
'Internet',
'Mortgage',
'Water',
'Power',
'Starting Balances',
'Misc',
'Income',
]);
await expect(page).toMatchThemeScreenshots();
});

// Page Header Tests

test('checks that clicking the Actual logo in the page header opens the budget page menu', async () => {
const budgetPage = await navigation.goToBudgetPage();
await budgetPage.waitForBudgetTable();

await budgetPage.openBudgetPageMenu();

const budgetPageMenuModal = page.getByRole('dialog');

await expect(budgetPageMenuModal).toBeVisible();
await expect(page).toMatchThemeScreenshots();
});

test("checks that clicking the left arrow in the page header shows the previous month's budget", async () => {
const budgetPage = await navigation.goToBudgetPage();
await budgetPage.waitForBudgetTable();

const selectedMonth = await budgetPage.getSelectedMonth();
const displayMonth = monthUtils.format(
selectedMonth,
budgetPage.MONTH_HEADER_DATE_FORMAT,
);

await expect(budgetPage.heading).toHaveText(displayMonth);

const previousMonth = await budgetPage.goToPreviousMonth();
const previousDisplayMonth = monthUtils.format(
previousMonth,
budgetPage.MONTH_HEADER_DATE_FORMAT,
);

await expect(budgetPage.heading).toHaveText(previousDisplayMonth);
await expect(page).toMatchThemeScreenshots();
});

test('checks that clicking the month in the page header opens the month menu modal', async () => {
const budgetPage = await navigation.goToBudgetPage();
await budgetPage.waitForBudgetTable();

const selectedMonth = await budgetPage.getSelectedMonth();

await budgetPage.openMonthMenu();

const monthMenuModal = page.getByRole('dialog');
const monthMenuModalHeading = monthMenuModal.getByRole('heading');

const displayMonth = monthUtils.format(
selectedMonth,
budgetPage.MONTH_HEADER_DATE_FORMAT,
);
await expect(monthMenuModalHeading).toHaveText(displayMonth);
await expect(page).toMatchThemeScreenshots();
});

test("checks that clicking the right arrow in the page header shows the next month's budget", async () => {
const budgetPage = await navigation.goToBudgetPage();
await budgetPage.waitForBudgetTable();

const selectedMonth = await budgetPage.getSelectedMonth();
const displayMonth = monthUtils.format(
selectedMonth,
budgetPage.MONTH_HEADER_DATE_FORMAT,
);

await expect(budgetPage.heading).toHaveText(displayMonth);

const nextMonth = await budgetPage.goToNextMonth();
const nextDisplayMonth = monthUtils.format(
nextMonth,
budgetPage.MONTH_HEADER_DATE_FORMAT,
);

await expect(budgetPage.heading).toHaveText(nextDisplayMonth);
await expect(page).toMatchThemeScreenshots();
});

// Category / Category Group Menu Tests

test('checks that clicking the category group name opens the category group menu modal', async () => {
const budgetPage = await navigation.goToBudgetPage();
await budgetPage.waitForBudgetTable();

const categoryGroupName = await budgetPage.getCategoryGroupNameForRow(0);
await budgetPage.openCategoryGroupMenu(categoryGroupName);

const categoryMenuModalHeading = page
.getByRole('dialog')
.getByRole('heading');

await expect(categoryMenuModalHeading).toHaveText(categoryGroupName);
await expect(page).toMatchThemeScreenshots();
});

test('checks that clicking the category name opens the category menu modal', async () => {
const budgetPage = await navigation.goToBudgetPage();
await budgetPage.waitForBudgetTable();

const categoryName = await budgetPage.getCategoryNameForRow(0);
await budgetPage.openCategoryMenu(categoryName);

const categoryMenuModalHeading = page
.getByRole('dialog')
.getByRole('heading');

await expect(categoryMenuModalHeading).toHaveText(categoryName);
await expect(page).toMatchThemeScreenshots();
});

// Budgeted Cell Tests

test('checks that clicking the budgeted cell opens the budget menu modal', async () => {
const budgetPage = await navigation.goToBudgetPage();
await budgetPage.waitForBudgetTable();

const categoryName = await budgetPage.getCategoryNameForRow(0);
await budgetPage.openBudgetMenu(categoryName);

const budgetMenuModalHeading = page
.getByRole('dialog')
.getByRole('heading');

await expect(budgetMenuModalHeading).toHaveText(categoryName);
await expect(page).toMatchThemeScreenshots();
});

test('updates the budgeted amount', async () => {
const budgetPage = await navigation.goToBudgetPage();
await budgetPage.waitForBudgetTable();

const categoryName = await budgetPage.getCategoryNameForRow(0);

// Set to 100.00
await budgetPage.setBudget(categoryName, 10000);

const budgetedButton =
await budgetPage.getButtonForBudgeted(categoryName);

await expect(budgetedButton).toHaveText('100.00');
await expect(page).toMatchThemeScreenshots();
});

// Spent Cell Tests

test('checks that clicking spent cell redirects to the category transactions page', async () => {
const budgetPage = await navigation.goToBudgetPage();
await budgetPage.waitForBudgetTable();

const categoryName = await budgetPage.getCategoryNameForRow(0);
const accountPage = await budgetPage.openSpentPage(categoryName);

await expect(accountPage.heading).toContainText(categoryName);
await expect(accountPage.transactionList).toBeVisible();
await expect(page).toMatchThemeScreenshots();
});

// Balance Cell Tests

test('checks that clicking the balance cell opens the balance menu modal', async () => {
const budgetPage = await navigation.goToBudgetPage();
await budgetPage.waitForBudgetTable();

const categoryName = await budgetPage.getCategoryNameForRow(0);
await budgetPage.openBalanceMenu(categoryName);

const balanceMenuModalHeading = page
.getByRole('dialog')
.getByRole('heading');

await expect(balanceMenuModalHeading).toHaveText(categoryName);
await expect(page).toMatchThemeScreenshots();
});

if (budgetType === 'Envelope') {
test('checks that clicking the To Budget/Overbudgeted amount opens the budget summary menu modal', async () => {
const budgetPage = await navigation.goToBudgetPage();
await budgetPage.waitForBudgetTable();

await budgetPage.openEnvelopeBudgetSummaryMenu();

const summaryModalHeading = page
.getByRole('dialog')
.getByRole('heading');

await expect(summaryModalHeading).toHaveText('Budget Summary');
await expect(page).toMatchThemeScreenshots();
});
}

if (budgetType === 'Tracking') {
test('checks that clicking the Saved/Projected Savings/Overspent amount opens the budget summary menu modal', async () => {
const budgetPage = await navigation.goToBudgetPage();
await budgetPage.waitForBudgetTable();

await budgetPage.openTrackingBudgetSummaryMenu();

const summaryModalHeading = page
.getByRole('dialog')
.getByRole('heading');

await expect(summaryModalHeading).toHaveText('Budget Summary');
await expect(page).toMatchThemeScreenshots();
});
}
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ export class MobileAccountPage {

this.heading = page.getByRole('heading');
this.balance = page.getByTestId('transactions-balance');
this.noTransactionsFoundError = page.getByText('No transactions');
this.noTransactionsMessage = page.getByText('No transactions');
this.searchBox = page.getByPlaceholder(/^Search/);
this.transactionList = page.getByLabel('transaction list');
this.transactionList = page.getByLabel('Transaction list');
this.transactions = this.transactionList.getByRole('button');
this.createTransactionButton = page.getByRole('button', {
name: 'Add Transaction',
Expand Down
Loading

0 comments on commit a28fb93

Please sign in to comment.