Skip to content

Commit

Permalink
fix: renterd hostd config tests
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfreska committed Jun 7, 2024
1 parent e935c2b commit 1d1f056
Show file tree
Hide file tree
Showing 43 changed files with 1,174 additions and 13 deletions.
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
GITHUB_TOKEN=secret_token
NOTION_TOKEN=secret_token
ASSETS=/User/bob/web/assets
HOSTD_E2E_TEST_API_URL=https://hostd.zen.local
HOSTD_E2E_TEST_API_PASSWORD=password
RENTERD_E2E_TEST_API_URL=https://renterd.zen.local
RENTERD_E2E_TEST_API_PASSWORD=password
WALLETD_E2E_TEST_API_URL=https://walletd.zen.local
WALLETD_E2E_TEST_API_PASSWORD=password

# Make Go use UTC for time formatting
TZ=UTC
46 changes: 38 additions & 8 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,6 @@ jobs:
- name: Test TypeScript
shell: bash
run: npx nx affected --target=test --parallel=5
- name: Install playwright deps for e2e
shell: bash
run: npx playwright install-deps
- name: Test e2e
shell: bash
run: npx nx affected --target=e2e --parallel=5
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Build
shell: bash
run: npx nx affected --target=build --configuration=production --parallel=5
Expand All @@ -59,6 +51,44 @@ jobs:
shell: bash
# issue with parallelism
run: npx nx affected --target=build --configuration=export --parallel=5
test-e2e:
runs-on: ubuntu-latest
# Only run one test-e2e job at a time because they mutate the same data
concurrency: test-e2e
if: ${{ github.event_name == 'pull_request' && github.event.action != 'closed' }}
steps:
- name: Checkout all commits
uses: actions/checkout@v3
with:
fetch-depth: 0
# Full setup required since building the JS SDK requires Go
- name: Setup
uses: ./.github/actions/setup-all
with:
node_version: 20.10.0
go_version: 1.21.7
# The SDK is referenced via dist in the tsconfig.base.json
# because the next executor does not actually support
# buildLibsFromSource=false
# With this configuration NX does not build the SDK as expected
# when it is an app dependency
- name: Force build SDK
shell: bash
run: npx nx run sdk:build
- name: Install playwright deps for e2e
shell: bash
run: npx playwright install-deps
- name: Test e2e
shell: bash
run: npx nx affected --target=e2e --parallel=5
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
RENTERD_E2E_TEST_API_URL: ${{ secrets.RENTERD_E2E_TEST_API_URL }}
RENTERD_E2E_TEST_API_PASSWORD: ${{ secrets.RENTERD_E2E_TEST_API_PASSWORD }}
HOSTD_E2E_TEST_API_URL: ${{ secrets.HOSTD_E2E_TEST_API_URL }}
HOSTD_E2E_TEST_API_PASSWORD: ${{ secrets.HOSTD_E2E_TEST_API_PASSWORD }}
WALLETD_E2E_TEST_API_URL: ${{ secrets.WALLETD_E2E_TEST_API_URL }}
WALLETD_E2E_TEST_API_PASSWORD: ${{ secrets.WALLETD_E2E_TEST_API_PASSWORD }}
test-go:
# Run matrix since Go modules are used across all platforms
runs-on: ${{ matrix.os }}
Expand Down
32 changes: 32 additions & 0 deletions .github/workflows/release-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,32 @@ jobs:
- name: Test TypeScript
shell: bash
run: npx nx run-many --target=test --all --parallel=5
# This job should always pass because the workflow is running run against code that
# was already linted and tested in PR.
# This runs in parallel to the build and release process as an extra check but does
# not actually block the release if job fails.
test-e2e:
runs-on: ubuntu-latest
# Only run one test-e2e job at a time because they mutate the same data
concurrency: test-e2e
steps:
- name: Checkout all commits
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup
uses: ./.github/actions/setup-all
with:
node_version: 20.10.0
go_version: 1.21.7
# The SDK is referenced via dist in the tsconfig.base.json
# because the next executor does not actually support
# buildLibsFromSource=false
# With this configuration NX does not build the SDK as expected
# when it is an app dependency
- name: Force build SDK
shell: bash
run: npx nx run sdk:build
- name: Install playwright deps for e2e
shell: bash
run: npx playwright install-deps
Expand All @@ -148,6 +174,12 @@ jobs:
run: npx nx run-many --target=e2e --all --parallel=5
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
RENTERD_E2E_TEST_API_URL: ${{ secrets.RENTERD_E2E_TEST_API_URL }}
RENTERD_E2E_TEST_API_PASSWORD: ${{ secrets.RENTERD_E2E_TEST_API_PASSWORD }}
HOSTD_E2E_TEST_API_URL: ${{ secrets.HOSTD_E2E_TEST_API_URL }}
HOSTD_E2E_TEST_API_PASSWORD: ${{ secrets.HOSTD_E2E_TEST_API_PASSWORD }}
WALLETD_E2E_TEST_API_URL: ${{ secrets.WALLETD_E2E_TEST_API_URL }}
WALLETD_E2E_TEST_API_PASSWORD: ${{ secrets.WALLETD_E2E_TEST_API_PASSWORD }}
# This job should always pass because the workflow is running run against code that
# was already linted and tested in PR.
# This runs in parallel to the build and release process as an extra check but does
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ The Sia web libraries provide developers with convenient TypeScript SDKs for usi
### Testing

- [walletd-e2e](walletd-e2e) - App for testing walletd.
- [renterd-e2e](renterd-e2e) - App for testing renterd.
- [hostd-e2e](hostd-e2e) - App for testing hostd.
- [@siafoundation/walletd-mock](walletd-mock) - `walletd` data and API mock library for testing.
- [@siafoundation/sia-central-mock](sia-central-mock) - Sia Central data and API mock library for testing.

Expand Down
25 changes: 25 additions & 0 deletions apps/hostd-e2e/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"extends": ["plugin:playwright/recommended", "../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
},
{
"files": ["src/**/*.{ts,js,tsx,jsx}"],
"rules": {}
}
],
"rules": {
"playwright/expect-expect": "off"
}
}
1 change: 1 addition & 0 deletions apps/hostd-e2e/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
output
79 changes: 79 additions & 0 deletions apps/hostd-e2e/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { defineConfig, devices } from '@playwright/test'
import { nxE2EPreset } from '@nx/playwright/preset'

import { workspaceRoot } from '@nx/devkit'

// For CI, you may want to set BASE_URL to the deployed application.
const baseURL = process.env['BASE_URL'] || 'https://host.local'

/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
...nxE2EPreset(__filename, { testDir: './src' }),
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
baseURL,
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
video: 'on-first-retry',
},
expect: {
// Raise the timeout because it is running against next dev mode
// which requires compilation the first to a page is visited
timeout: 10_000,
},
outputDir: 'output',
/* Run your local dev server before starting the tests */
webServer: {
command: 'npx nx serve hostd',
url: baseURL,
reuseExistingServer: !process.env.CI,
cwd: workspaceRoot,
},
// Run the tests serially as they may mutate the state of the same application.
workers: 1,
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},

// Disable firefox and webkit to save time since tests are running serially.
// {
// name: 'firefox',
// use: { ...devices['Desktop Firefox'] },
// },

// {
// name: 'webkit',
// use: { ...devices['Desktop Safari'] },
// },

// Uncomment for mobile browsers support
/* {
name: 'Mobile Chrome',
use: { ...devices['Pixel 5'] },
},
{
name: 'Mobile Safari',
use: { ...devices['iPhone 12'] },
}, */

// Uncomment for branded browsers
/* {
name: 'Microsoft Edge',
use: { ...devices['Desktop Edge'], channel: 'msedge' },
},
{
name: 'Google Chrome',
use: { ...devices['Desktop Chrome'], channel: 'chrome' },
} */
],
})
19 changes: 19 additions & 0 deletions apps/hostd-e2e/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "hostd-e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/hostd-e2e/src",
"projectType": "application",
"implicitDependencies": ["hostd"],
"targets": {
"e2e": {
"executor": "@nx/playwright:playwright",
"outputs": ["{workspaceRoot}/dist/.playwright/apps/hostd-e2e"],
"options": {
"config": "apps/hostd-e2e/playwright.config.ts"
}
},
"lint": {
"executor": "@nx/eslint:lint"
}
}
}
11 changes: 11 additions & 0 deletions apps/hostd-e2e/src/fixtures/clearToasts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Page } from '@playwright/test'

export async function clearToasts({ page }: { page: Page }) {
const clearButtons = page.getByTestId('toasts').locator('button')
while ((await clearButtons.count()) > 0) {
await clearButtons.first().click()
// Timeout required because the toast animation is not instantaneous.
// eslint-disable-next-line playwright/no-wait-for-timeout
await page.waitForTimeout(1000)
}
}
23 changes: 23 additions & 0 deletions apps/hostd-e2e/src/fixtures/click.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Locator, expect } from '@playwright/test'

export async function clickAndWaitIfEnabled(
locator: Locator,
waitForLocator?: Locator
) {
const isDisabled = await locator.isDisabled()
if (!isDisabled) {
await locator.click()
if (waitForLocator) {
await expect(waitForLocator).toBeVisible()
}
return true
}
return false
}

export async function clickAndWait(locator: Locator, waitForLocator?: Locator) {
await locator.click()
if (waitForLocator) {
await expect(waitForLocator).toBeVisible()
}
}
71 changes: 71 additions & 0 deletions apps/hostd-e2e/src/fixtures/configResetAllSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Page } from '@playwright/test'
import { setSwitchByLabel } from './switchValue'
import { setViewMode } from './configViewMode'
import { fillTextInputByName } from './textInput'
import { fillSelectInputByName } from './selectInput'
import { clearToasts } from './clearToasts'
import { clickAndWaitIfEnabled } from './click'

export async function configResetAllSettings({ page }: { page: Page }) {
await setViewMode({ page, state: 'advanced' })

// host
await setSwitchByLabel(page, 'acceptingContracts', false)
await fillTextInputByName(page, 'netAddress', 'foobar.com:9880')
await fillTextInputByName(page, 'maxContractDuration', '6')

// pricing
await fillSelectInputByName(page, 'pinnedCurrency', 'USD')
await fillTextInputByName(page, 'pinnedThreshold', '3')

await setSwitchByLabel(page, 'shouldPinStoragePrice', false)
await fillTextInputByName(page, 'storagePrice', '10')
await setSwitchByLabel(page, 'shouldPinStoragePrice', true)
await fillTextInputByName(page, 'storagePricePinned', '5')
await setSwitchByLabel(page, 'shouldPinStoragePrice', false)

await setSwitchByLabel(page, 'shouldPinEgressPrice', false)
await fillTextInputByName(page, 'egressPrice', '10')
await setSwitchByLabel(page, 'shouldPinEgressPrice', true)
await fillTextInputByName(page, 'egressPricePinned', '5')
await setSwitchByLabel(page, 'shouldPinEgressPrice', false)

await setSwitchByLabel(page, 'shouldPinIngressPrice', false)
await fillTextInputByName(page, 'ingressPrice', '10')
await setSwitchByLabel(page, 'shouldPinIngressPrice', true)
await fillTextInputByName(page, 'ingressPricePinned', '5')
await setSwitchByLabel(page, 'shouldPinIngressPrice', false)

await fillTextInputByName(page, 'collateralMultiplier', '2')

await setSwitchByLabel(page, 'shouldPinMaxCollateral', false)
await setSwitchByLabel(page, 'shouldPinMaxCollateral', false)
await setSwitchByLabel(page, 'autoMaxCollateral', false)
await fillTextInputByName(page, 'maxCollateral', '10')
await setSwitchByLabel(page, 'shouldPinMaxCollateral', true)
await fillTextInputByName(page, 'maxCollateralPinned', '5')
await setSwitchByLabel(page, 'shouldPinMaxCollateral', false)

await fillTextInputByName(page, 'contractPrice', '0.2')
await fillTextInputByName(page, 'baseRPCPrice', '1')
await fillTextInputByName(page, 'sectorAccessPrice', '1')
await fillTextInputByName(page, 'priceTableValidity', '30')

// accounts
await fillTextInputByName(page, 'accountExpiry', '30')
await fillTextInputByName(page, 'maxAccountBalance', '10')

// bandwidth
await fillTextInputByName(page, 'ingressLimit', '0')
await fillTextInputByName(page, 'egressLimit', '0')

// DNS
await fillSelectInputByName(page, 'dnsProvider', '')

// save
await clickAndWaitIfEnabled(
page.getByText('Save changes'),
page.getByText('Settings have been saved')
)
await clearToasts({ page })
}
24 changes: 24 additions & 0 deletions apps/hostd-e2e/src/fixtures/configViewMode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Page } from '@playwright/test'
import { getSwitchByLabel } from './switchValue'

export async function setViewMode({
page,
state,
}: {
page: Page
state: 'advanced' | 'basic'
}) {
const { el, value } = await getViewMode({ page })
if (state !== value) {
await el.click()
}
}

export async function getViewMode({ page }: { page: Page }) {
await page.getByRole('button', { name: 'View' }).click()
const { el, value } = await getSwitchByLabel(page, 'configViewMode')
return {
el,
value: value ? 'advanced' : 'basic',
}
}
Loading

0 comments on commit 1d1f056

Please sign in to comment.