Skip to content

Commit bf41d66

Browse files
committed
Move smoke-test to playwright
1 parent 468ed21 commit bf41d66

File tree

6 files changed

+235
-5
lines changed

6 files changed

+235
-5
lines changed

.github/workflows/build-test.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -635,8 +635,6 @@ jobs:
635635
k8s-distribution: ${{ matrix.cluster.distribution }}
636636
k8s-version: ${{ matrix.cluster.version }}
637637
k8s-instance-type: ${{ matrix.cluster.instance_type }}
638-
testim-access-token: '${{ secrets.TESTIM_ACCESS_TOKEN }}'
639-
testim-branch: ${{ github.head_ref == 'main' && 'master' || github.head_ref }}
640638
aws-access-key-id: '${{ secrets.E2E_SUPPORT_BUNDLE_AWS_ACCESS_KEY_ID }}'
641639
aws-secret-access-key: '${{ secrets.E2E_SUPPORT_BUNDLE_AWS_SECRET_ACCESS_KEY }}'
642640
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
@@ -4125,7 +4123,6 @@ jobs:
41254123
- ci-test-kots
41264124
# testim tests
41274125
- validate-existing-online-install-minimal
4128-
- validate-smoke-test
41294126
- validate-version-history-pagination
41304127
- validate-change-license
41314128
- validate-min-kots-version
@@ -4137,6 +4134,7 @@ jobs:
41374134
- validate-support-bundle
41384135
- validate-gitops
41394136
# playwright tests
4137+
- validate-smoke-test
41404138
- validate-backup-and-restore
41414139
- validate-no-required-config
41424140
- validate-config

e2e/inventory/inventory.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ func NewRegressionTest() Test {
3535

3636
func NewSmokeTest() Test {
3737
return Test{
38+
ID: "smoke-test",
3839
Name: "Smoke Test",
39-
TestimSuite: "smoke-test",
4040
Namespace: "smoke-test",
41+
AppSlug: "qakotstestim",
4142
UpstreamURI: "qakotstestim/github-actions-qa",
4243
NeedsSnapshots: true,
4344
}

e2e/playwright/tests/shared/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './login';
2-
export * from './upload-license';
2+
export * from './upload-license';
3+
export * from './validate-deploy-logs';
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export const validateDeployLogs = async (page, expect) => {
2+
await expect(page.getByText('dryrunStdout')).toBeVisible();
3+
await expect(page.getByText('dryrunStderr')).toBeVisible();
4+
await expect(page.getByText('applyStdout')).toBeVisible();
5+
await expect(page.getByText('applyStderr')).toBeVisible();
6+
await expect(page.getByText('helmStdout')).toBeVisible();
7+
await expect(page.getByText('helmStderr')).toBeVisible();
8+
await page.getByText('dryrunStderr').click();
9+
await page.getByText('applyStdout').click();
10+
await expect(page.locator('.view-lines')).toContainText('created');
11+
await page.getByRole('button', { name: 'Ok, got it!' }).click();
12+
};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
apiVersion: kots.io/v1beta1
2+
kind: License
3+
metadata:
4+
name: githubactionqa
5+
spec:
6+
appSlug: qakotstestim
7+
channelID: 1qcbLyQFdfxq28RbSN4wEtqaxcZ
8+
channelName: Github Actions QA
9+
customerName: GitHub Action QA
10+
endpoint: https://replicated.app
11+
entitlements:
12+
expires_at:
13+
description: License Expiration
14+
title: Expiration
15+
value: ""
16+
valueType: String
17+
isAirgapSupported: true
18+
isGitOpsSupported: true
19+
isSnapshotSupported: true
20+
licenseID: 1qcbXQRwHNCbYIchxIDwuLdLkVa
21+
licenseSequence: 1
22+
licenseType: prod
23+
signature: eyJsaWNlbnNlRGF0YSI6ImV5SmhjR2xXWlhKemFXOXVJam9pYTI5MGN5NXBieTkyTVdKbGRHRXhJaXdpYTJsdVpDSTZJa3hwWTJWdWMyVWlMQ0p0WlhSaFpHRjBZU0k2ZXlKdVlXMWxJam9pWjJsMGFIVmlZV04wYVc5dWNXRWlmU3dpYzNCbFl5STZleUpzYVdObGJuTmxTVVFpT2lJeGNXTmlXRkZTZDBoT1EySlpTV05vZUVsRWQzVk1aRXhyVm1FaUxDSnNhV05sYm5ObFZIbHdaU0k2SW5CeWIyUWlMQ0pqZFhOMGIyMWxjazVoYldVaU9pSkhhWFJJZFdJZ1FXTjBhVzl1SUZGQklpd2lZWEJ3VTJ4MVp5STZJbkZoYTI5MGMzUmxjM1JwYlNJc0ltTm9ZVzV1Wld4SlJDSTZJakZ4WTJKTWVWRkdaR1o0Y1RJNFVtSlRUalIzUlhSeFlYaGpXaUlzSW1Ob1lXNXVaV3hPWVcxbElqb2lSMmwwYUhWaUlFRmpkR2x2Ym5NZ1VVRWlMQ0pzYVdObGJuTmxVMlZ4ZFdWdVkyVWlPakVzSW1WdVpIQnZhVzUwSWpvaWFIUjBjSE02THk5eVpYQnNhV05oZEdWa0xtRndjQ0lzSW1WdWRHbDBiR1Z0Wlc1MGN5STZleUpsZUhCcGNtVnpYMkYwSWpwN0luUnBkR3hsSWpvaVJYaHdhWEpoZEdsdmJpSXNJbVJsYzJOeWFYQjBhVzl1SWpvaVRHbGpaVzV6WlNCRmVIQnBjbUYwYVc5dUlpd2lkbUZzZFdVaU9pSWlMQ0oyWVd4MVpWUjVjR1VpT2lKVGRISnBibWNpZlgwc0ltbHpRV2x5WjJGd1UzVndjRzl5ZEdWa0lqcDBjblZsTENKcGMwZHBkRTl3YzFOMWNIQnZjblJsWkNJNmRISjFaU3dpYVhOVGJtRndjMmh2ZEZOMWNIQnZjblJsWkNJNmRISjFaWDE5IiwiaW5uZXJTaWduYXR1cmUiOiJleUpzYVdObGJuTmxVMmxuYm1GMGRYSmxJam9pV2tKVWMyMWxRVW81YW5Vd01EVmlSbkpGVDNWMlpYRkNkMmt5UjNjeE5rSXhNRXR6VWtSb1JqRm9kMVYwVTNSTWVWRkhUR2g2Ym5OWFVIRndVR1JYTmxsSFZrOVBOWFpDVlU1RGJIZHpURTlETDIxRUt6TnhOWEJNVGxkdVF6SmplbTVGTDA0eE1EVnJWSFJYVDNGa1RXdzFTa3B3T1dwbFNETkhNbm93Y21kelFXOVRZVWd6Y20xMmNYZERhekpGTldabmExZE1Sa0U0TDBGbVNYZEZRbU5FY1dOdFpEWnViVFJFYkZoQlJVcE9hRlJUYjFWNVpTdEpXR2xKTlZGWFZuTmlhR2ROWml0bVYyeG1lV2hRYkVsMmNDODVjVUYyTDI1blFUTkhSVmh0UVZOeU1XSXlhVkZpU25SaVpGQlVkM1JDVFdoalJscDRabE53WlZaRk4xWk9MelJ4VG1GdE1ubGpOMEpEZW1GcGNtdG1PRzlETUZkc1JtaHpWVFkzSzB0ck9HRmxRM0pKVEZCR1ZWcHVjVFF5ZUdaMVZ6UXZWekJXU21VemVrVkRjSGx4YmtkMlptNDNPRlZVYTJoblRuVXlWemRuUFQwaUxDSndkV0pzYVdOTFpYa2lPaUl0TFMwdExVSkZSMGxPSUZCVlFreEpReUJMUlZrdExTMHRMVnh1VFVsSlFrbHFRVTVDWjJ0eGFHdHBSemwzTUVKQlVVVkdRVUZQUTBGUk9FRk5TVWxDUTJkTFEwRlJSVUYyWVRFNVRFUlFWQ3R6VTJaeE5XMU9iemw2YzF4dVNIRk5LMGhSSzFoclEyTk5WRTFaTUZGR1lTdDNRa1p6WWtwdFVFTjVheXRqTTNORmRUTTFSMDVZUTBsamVqWlFUbk0yZGtOdWFuQmhNVFJwZGpOMVdseHVSRmxzY0hCU2QyZzFPSEJ5UldoYVZrOUhXVmxhYm5KeVZIWXllV3Q2VUhWMFNuZFdUazFhUWpSQ1RsTjRWalZFYURCd1dFZ3hWaXRxV1V0VmJFRlJhMXh1Y25aUVZVRk5ObmsxUTBscmVGUjBOM3B1U0U5eVMwWlJRMVJGZWxOS1lsUllUalJPYjNkdVdscFJZVFY2ZWxsWldsTTRkV0pHVFVaNEswVlRVbk5wYjF4dWJWUXZWMEpEUzA1RlIzbEpOMlY0WkdoTlZHMXFNRFUyVkZoUmFHaG1VVk01WkZVclpYTk5NelprSzJsSVRHTkRaeTlyWmtaNVlTdFRiM1puVlVJdmJGeHVZVWhCU0ZKM2RrTkJLMjVzTkRKelpFSlZkRXBIU21VcmRpOUtPVVYxY2tod01pdFNRMnM0Ylc1aFVYUkdNVTh5TmpKeFExUXhaQ3R5Tm5oTWEzcHpORnh1WTFGSlJFRlJRVUpjYmkwdExTMHRSVTVFSUZCVlFreEpReUJMUlZrdExTMHRMVnh1SWl3aWEyVjVVMmxuYm1GMGRYSmxJam9pWlhsS2VtRlhaSFZaV0ZJeFkyMVZhVTlwU25sTk0yUkhWbXR3YzFReFdqQmpNSGcwV1d4R1NsRnFTbEpNTUZKdVRUSkdSVlZVYUhSamJFcE5Za2hvY1dWRlZtMWpXR1JJWkdwYWNWa3dkR0ZPVkdoaFZHcFNWRmRyZUVOVFNFSkpaRlJaY21ReVJuaGliWEF4VGpKS1dXSnFaSFpQV0ZVeVVrZFNhVkV3TVcxWmJrNWFXV3h3UTJKR1ZuZFdSRlpUVjBkdk0xa3lXakpWVms1RFkwaE9ZVk5zU2pCa1dIQlJZMWh3UjFwc1FtMWliVmt3VkRGSmNtTkhPVk5sYld4RlRsaHdTV0ZwT1Vsa1ZYUk9XVEprZVZsVVRrZGxWWE15WW5wU2JGTnNSbWxaYTFKWFpHMXNTVkpUZEhSYWEwa3hZMjFXYmxSR1RqRldSVTUxVjJ0amVGWnVTa1ZPYTJocVZEQmFhMlZFVGpOU1IxcEdZbFJvZWxOV1dsZE9XRmt5VlVoVk5WRnJhRVJPZW1nd1VqRk9SRTFFU1ROUlZtUmFWR3RrZWxkRlZqTmtNMmN5VVZkMFZGTXdXbXROTVhCRFRVWnZkMkY1ZEd4Wk0yczFUMWRPVUUxc1NuUlVTRkpGVFcwNVEwNHdSak5PYlhBeVRVVktOVmxWUmxST2JYUnlTekZrU0Zvd09XaFhhbGwzVjBOMFdGSnVXbWxOUkVweFZGZFpNMk50ZEV4VlZYaDZXbXhDTlZaVVpGQmhSWGN6VVcxS1JWZEdSazVrUkVwYVdXMTRNMUpZY0UxVmF6bHFWMnhhTm1GWVdrOWxiRnBPVXpKbmNsWnRZemxRVTBselNXMWtjMkl5U21oaVJYUnNaVlZzYTBscWIybFpiVkpzV2xSVk1rNVVXWGRaTWxwcFRrUk9hazlYU1hsUFIwcHRUMVJvYkZsWFRtaGFiVVV5VGtSWmFXWlJQVDBpZlE9PSJ9
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
import { test, expect } from '@playwright/test';
2+
import { login, uploadLicense, validateDeployLogs } from '../shared';
3+
4+
const { execSync } = require("child_process");
5+
6+
test('smoke test', async ({ page }) => {
7+
test.setTimeout(5 * 60 * 1000); // 5 minutes
8+
await login(page);
9+
await uploadLicense(page, expect);
10+
await expect(page.locator('#app')).toContainText('Install in airgapped environment', { timeout: 15000 });
11+
await page.getByText('download App Name from the Internet').click();
12+
await expect(page.locator('#app')).toContainText('Installing your license');
13+
await expect(page.locator('h3')).toContainText('My Example Config', { timeout: 30000 });
14+
await page.locator('#a_bool-group').getByText('a bool field').click();
15+
await page.locator('#a_required_text-group').getByRole('textbox').click();
16+
await page.locator('#a_required_text-group').getByRole('textbox').fill('my required text field');
17+
await expect(page.locator('#version_sequence-group')).toContainText('This version is 0');
18+
await page.getByRole('button', { name: 'Continue' }).click();
19+
await expect(page.locator('#app')).toContainText('Results', { timeout: 30000 });
20+
await expect(page.locator('#app')).toContainText('Sequence is 0');
21+
await page.getByRole('button', { name: 'Deploy' }).click();
22+
await page.getByRole('button', { name: 'Deploy anyway' }).click();
23+
await expect(page.locator('#app')).toContainText('Ready', { timeout: 30000 });
24+
await expect(page.locator('#app')).toContainText('Currently deployed version', { timeout: 15000 });
25+
await expect(page.locator('#app')).toContainText('Check for update');
26+
await expect(page.locator('#app')).toContainText('Configure automatic updates');
27+
await expect(page.locator('#app')).toContainText('Redeploy', { timeout: 15000 });
28+
await page.getByRole('link', { name: 'Version history' }).click();
29+
await expect(page.locator('.currentVersion--wrapper')).toContainText('Sequence 0');
30+
await expect(page.locator('#app')).toContainText('Currently deployed version');
31+
await expect(page.locator('#app')).toContainText('Check for update');
32+
await expect(page.locator('#app')).toContainText('Configure automatic updates');
33+
await expect(page.getByRole('button')).toContainText('Redeploy');
34+
await page.getByText('Configure automatic updates').click();
35+
await expect(page.locator('.ConfigureUpdatesModal')).toContainText('Default');
36+
await expect(page.locator('.ConfigureUpdatesModal')).toContainText('Every 4 hours');
37+
await expect(page.locator('label')).toContainText('Enable automatic deployment');
38+
await page.locator('.replicated-select__control').click();
39+
await page.locator('.replicated-select__option').getByText('Weekly', { exact: true }).click();
40+
await expect(page.locator('.ConfigureUpdatesModal')).toContainText('Weekly');
41+
await expect(page.locator('.ConfigureUpdatesModal')).toContainText('At 12:00 AM, only on Sunday');
42+
await page.getByRole('button', { name: 'Update', exact: true }).click();
43+
await expect(page.getByText('Automatically check for updates', { exact: true })).not.toBeVisible();
44+
await page.locator('span[data-tip="View deploy logs"]').first().click();
45+
await validateDeployLogs(page, expect);
46+
await page.reload();
47+
await page.getByRole('link', { name: 'Dashboard' }).click();
48+
await expect(page.getByText('App Name')).toBeVisible();
49+
await expect(page.locator('.Dashboard--appIcon')).toBeVisible();
50+
await expect(page.locator('p').filter({ hasText: 'License' })).toBeVisible();
51+
await page.getByText('Configure automatic updates').click();
52+
await expect(page.locator('.ConfigureUpdatesModal')).toContainText('Weekly');
53+
await expect(page.locator('.ConfigureUpdatesModal')).toContainText('At 12:00 AM, only on Sunday');
54+
await expect(page.locator('label')).toContainText('Enable automatic deployment');
55+
await page.getByRole('button', { name: 'Cancel' }).click();
56+
await page.locator('svg.icons.clickable[data-tip="View release notes"]').click();
57+
await expect(page.getByLabel('Release Notes').getByRole('paragraph')).toContainText('release notes - updates');
58+
await page.getByRole('button', { name: 'Close' }).click();
59+
await page.locator('span[data-tip="View deploy logs"]').click();
60+
await validateDeployLogs(page, expect);
61+
await page.getByRole('link', { name: 'Config', exact: true }).click();
62+
await expect(page.locator('h3')).toContainText('My Example Config');
63+
await expect(page.locator('#version_sequence-group')).toContainText('This version is 1');
64+
await expect(page.getByRole('button', { name: 'Save config' })).toBeVisible();
65+
await page.getByRole('link', { name: 'Troubleshoot' }).click();
66+
await expect(page.getByRole('button', { name: 'Analyze App Name' })).toBeVisible();
67+
await page.getByRole('link', { name: 'License' }).click();
68+
await expect(page.locator('#app')).toContainText('Airgap enabled');
69+
await expect(page.locator('#app')).toContainText('Snapshots enabled');
70+
await expect(page.getByRole('button', { name: 'Sync license' })).toBeVisible();
71+
await page.getByRole('link', { name: 'View files' }).click();
72+
await page.getByText('upstream', { exact: true }).click();
73+
await page.getByRole('listitem', { name: 'config.yaml' }).locator('div').click();
74+
await expect(page.locator('.view-lines')).toContainText('apiVersion');
75+
await page.getByText('Click here', { exact: true }).click();
76+
await expect(page.getByRole('heading')).toContainText('Edit patches for your kots application');
77+
await expect(page.getByText('Copy command').first()).toBeVisible();
78+
79+
let downloadCommand = await page.locator('.react-prism.language-bash').first().textContent();
80+
if (!downloadCommand!.includes('download')) {
81+
throw new Error("Expected the download command to contain the word 'download'");
82+
}
83+
downloadCommand = `${downloadCommand} --overwrite`;
84+
console.log(downloadCommand, "\n");
85+
execSync(downloadCommand, {stdio: 'inherit'});
86+
87+
await expect(page.getByText('Copy command').last()).toBeVisible();
88+
let uploadCommand = await page.locator('.react-prism.language-bash').last().textContent();
89+
if (!uploadCommand!.includes('upload')) {
90+
throw new Error("Expected the upload command to contain the word 'upload'");
91+
}
92+
console.log(uploadCommand, "\n");
93+
execSync(uploadCommand, {stdio: 'inherit'});
94+
95+
await page.getByRole('button', { name: 'Ok, got it!' }).click();
96+
await page.getByRole('link', { name: 'Version history' }).click();
97+
await expect(page.locator('#app')).toContainText('KOTS Upload');
98+
await expect(page.getByText('Running checks', { exact: true }).first()).not.toBeVisible({ timeout: 30000 });
99+
await page.getByRole('button', { name: 'Deploy' }).first().click();
100+
await page.getByRole('button', { name: 'Deploy this version' }).click();
101+
await expect(page.locator('#app')).toContainText('Deploying');
102+
await expect(page.locator('#app')).toContainText('Currently deployed version');
103+
await expect(page.locator('#app')).toContainText('Application up to date.');
104+
await expect(page.locator('.currentVersion--wrapper')).toContainText('Sequence 1');
105+
await page.getByRole('link', { name: 'Registry settings' }).click();
106+
await page.getByPlaceholder('artifactory.some-big-bank.com').click();
107+
await page.getByPlaceholder('artifactory.some-big-bank.com').fill('ttl.sh');
108+
await page.getByPlaceholder('username').click();
109+
await page.getByPlaceholder('username').fill('admin');
110+
await page.getByPlaceholder('password').click();
111+
await page.getByPlaceholder('password').fill('admin');
112+
await page.getByRole('button', { name: 'Test connection' }).click();
113+
await expect(page.locator('form')).toContainText('Success!');
114+
await page.getByRole('button', { name: 'Save changes' }).click();
115+
await expect(page.getByRole('button', { name: 'Save changes' })).toBeDisabled();
116+
await expect(page.locator('.Loader')).toBeVisible();
117+
await expect(page.locator('#app')).toContainText('Writing manifest to image destination', { timeout: 30000 });
118+
await expect(page.getByRole('button', { name: 'Save changes' })).toBeEnabled({ timeout: 30000 });
119+
await expect(page.locator('.Loader')).not.toBeVisible();
120+
await page.getByRole('link', { name: 'Version history' }).click();
121+
await expect(page.locator('#app')).toContainText('Registry Change');
122+
await expect(page.locator('#app')).toContainText('Sequence 2');
123+
await page.getByRole('link', { name: 'Registry settings' }).click();
124+
await page.getByRole('button', { name: 'Stop using registry' }).click();
125+
await page.getByRole('button', { name: 'OK' }).click();
126+
await expect(page.locator('.Loader')).toBeVisible();
127+
await expect(page.getByRole('button', { name: 'Stop using registry' })).toBeDisabled();
128+
await expect(page.getByRole('button', { name: 'Save changes' })).toBeEnabled({ timeout: 30000 });
129+
await expect(page.locator('.Loader')).not.toBeVisible();
130+
await expect(page.getByPlaceholder('artifactory.some-big-bank.com')).toBeEmpty();
131+
await expect(page.getByPlaceholder('username')).toBeEmpty();
132+
await expect(page.getByPlaceholder('password')).toBeEmpty();
133+
await expect(page.getByPlaceholder('namespace')).toBeEmpty();
134+
await page.waitForTimeout(2000);
135+
await page.getByRole('link', { name: 'Version history' }).click();
136+
await expect(page.locator('#app')).toContainText('Sequence 3', { timeout: 10000 });
137+
await expect(page.locator('#app')).toContainText('Registry Change');
138+
await expect(page.locator('.NavItem').getByText('Application', { exact: true })).toBeVisible();
139+
await expect(page.locator('.NavItem').getByText('GitOps', { exact: true })).toBeVisible();
140+
await expect(page.locator('.NavItem').getByText('Snapshots', { exact: true })).toBeVisible();
141+
await expect(page.locator('div').filter({ hasText: /^Change passwordAdd new applicationLog out$/ }).getByRole('img')).toBeVisible();
142+
await page.locator('.NavItem').getByText('Snapshots', { exact: true }).click();
143+
await page.getByRole('link', { name: 'Settings & Schedule' }).click();
144+
await expect(page.locator('#app')).toContainText('Snapshot settings');
145+
await page.getByText('+ Add a new destination').click();
146+
await expect(page.getByRole('button', { name: 'Check for Velero' })).toBeVisible();
147+
await page.getByRole('button', { name: 'Check for Velero' }).click();
148+
await expect(page.getByLabel('Modal')).toContainText('Velero is installed on your cluster');
149+
await page.getByRole('button', { name: 'Ok, got it!' }).click();
150+
await page.getByRole('link', { name: 'Full Snapshots (Instance)' }).click();
151+
await expect(page.locator('#app')).toContainText('No snapshots yet');
152+
await page.getByRole('button', { name: 'Start a snapshot' }).click();
153+
await expect(page.locator('#app')).toContainText('In Progress');
154+
await expect(page.locator('#app')).toContainText('Completed', { timeout: 300000 });
155+
await page.getByText('Learn more').click();
156+
await page.getByRole('button', { name: 'Ok, got it!' }).click();
157+
await expect(page.locator('#app')).toContainText('Full Snapshots (Instance)');
158+
await page.getByRole('link', { name: 'Partial Snapshots (Application)' }).click();
159+
await page.getByRole('button', { name: 'Start a snapshot' }).click();
160+
await expect(page.locator('#app')).toContainText('In Progress');
161+
await expect(page.locator('#app')).toContainText('Completed', { timeout: 30000 });
162+
await expect(page.getByText('It’s recommend that you use')).toBeVisible();
163+
await page.getByText('Learn more').click();
164+
await page.getByRole('button', { name: 'Ok, got it!' }).click();
165+
await expect(page.locator('#app')).toContainText('Partial snapshots (Application)');
166+
await page.getByRole('link', { name: 'Full Snapshots (Instance)', exact: true }).click();
167+
await page.locator('.SnapshotRow--wrapper').click();
168+
await expect(page.locator('#app')).toContainText('Snapshot timeline');
169+
await page.getByText('View logs').click();
170+
await expect(page.locator('.view-lines')).toContainText('level=info');
171+
await page.getByRole('button', { name: 'Ok, got it!' }).click();
172+
await page.getByRole('link', { name: 'Full Snapshots (Instance)', exact: true }).click();
173+
await page.locator('svg.icons.clickable[data-tip="Restore from this backup"]').click();
174+
await expect(page.getByLabel('Modal')).toContainText('Restore from backup');
175+
await expect(page.getByLabel('Modal')).toContainText('Admin console & application');
176+
await expect(page.getByLabel('Modal')).toContainText('Application & metadata only');
177+
await expect(page.getByLabel('Modal')).toContainText('Only restores the admin console');
178+
await page.getByText('Application & metadata only', { exact: true }).click();
179+
await page.getByRole('button', { name: 'Cancel' }).click();
180+
await page.locator('svg.icons.clickable').last().click();
181+
await expect(page.getByLabel('Modal')).toContainText('Delete snapshot');
182+
await page.getByRole('button', { name: 'Delete snapshot' }).click();
183+
await expect(page.locator('#app')).toContainText('Deleting');
184+
await expect(page.locator('#app')).toContainText('No snapshots yet', { timeout: 15000 });
185+
await page.getByRole('link', { name: 'Settings & Schedule' }).click();
186+
await page.getByRole('button', { name: 'Update storage settings' }).click();
187+
await expect(page.locator('form')).toContainText('Settings updated', { timeout: 30000 });
188+
await page.getByRole('button', { name: 'Update schedule' }).click();
189+
await expect(page.locator('#app')).toContainText('Schedule updated');
190+
await page.locator('div').filter({ hasText: /^Change passwordAdd new applicationLog out$/ }).getByRole('img').click();
191+
await page.getByText('Log out', { exact: true }).click();
192+
await expect(page.getByPlaceholder('password')).toBeVisible();
193+
await expect(page.locator('#app')).toContainText('Enter the password to access the App Name admin console.');
194+
await expect(page.getByRole('button')).toContainText('Log in');
195+
});

0 commit comments

Comments
 (0)