Skip to content

Commit a10e399

Browse files
authored
feat: tests adaptation for new menus and pop-up for export (#39)
* feat(export): update page object model - ExportSettingsDialog - OverviewGroupRow - DocumentsPackageTab - DocumentPreviewPage * test(export): update export tests according to the new page object model * test(export): extract export tests into one file * test(export): use package ID and version instead of dashboard for documents export from dashboard * test(export): rename tests
1 parent 47bc8e5 commit a10e399

File tree

61 files changed

+2463
-2137
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+2463
-2137
lines changed
Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import { test as report, type Page } from '@playwright/test'
1+
import { type Page } from '@playwright/test'
22
import { Button, Link } from '@shared/components/base'
3-
import type { DownloadedTestFile } from '@shared/entities'
4-
import { DOWNLOAD_EXPECT } from '@test-setup'
53
import { CompareSelectDialog } from './BaseVersionPage/CompareSelectDialog'
64
import { ConfigureVersionTab } from './BaseVersionPage/ConfigureVersionTab'
75
import { CopyVersionDialog } from './BaseVersionPage/CopyVersionDialog'
@@ -14,7 +12,7 @@ import { DocumentPreviewPage } from './VersionPage/DocumentPreviewPage'
1412
import { VersionOverviewTab } from './VersionPage/VersionOverviewTab'
1513
import { VersionPageSidebar } from './VersionPage/VersionPageSidebar'
1614
import { VersionPageToolbar } from './VersionPage/VersionPageToolbar'
17-
import { getDownloadedFile } from '@services/utils'
15+
import { ExportSettingsDialog } from './BaseVersionPage/ExportSettingsDialog'
1816

1917
export abstract class BaseVersionPage {
2018

@@ -31,19 +29,9 @@ export abstract class BaseVersionPage {
3129
readonly oldRevisionDialog = new OldRevisionDialog(this.page)
3230
readonly methodsForUploadDialog = new MethodsForUploadDialog(this.page)
3331
readonly copyVersionDialog = new CopyVersionDialog(this.page)
32+
readonly exportSettingsDialog = new ExportSettingsDialog(this.page)
3433
readonly howToUploadBtn = new Button(this.page.getByTestId('HowToUploadButton'), 'How to Upload API documentation?')
3534
readonly createVersionLink = new Link(this.page.getByTestId('CreateVersionLink'), 'Create Version')
3635

3736
protected constructor(protected readonly page: Page) { }
38-
39-
async exportVersion(): Promise<DownloadedTestFile> {
40-
let file!: DownloadedTestFile
41-
await report.step('Export version', async () => {
42-
const downloadPromise = this.page.waitForEvent('download', { timeout: DOWNLOAD_EXPECT })
43-
await this.toolbar.exportBtn.click()
44-
const download = await downloadPromise
45-
file = await getDownloadedFile(download)
46-
})
47-
return file
48-
}
4937
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { type Page, test as report } from '@playwright/test'
2+
import { Button, Icon } from '@shared/components/base'
3+
import { BaseDialog } from '@shared/components/custom/dialogs/base/BaseDialog'
4+
import type { DownloadedTestFile } from '@shared/entities'
5+
import { PUBLISH_TIMEOUT } from '@test-setup'
6+
import { getDownloadedFile } from '@services/utils'
7+
import { RadioButton } from '@shared/components/base/buttons/RadioButton'
8+
9+
export class ExportSettingsDialog extends BaseDialog {
10+
11+
readonly reducedBtn = new RadioButton(this.rootLocator.locator('input[type="radio"][value="reducedSourceSpecifications"]'), 'Reduced source specifications')
12+
readonly combinedBtn = new RadioButton(this.rootLocator.locator('input[type="radio"][value="mergedSpecification"]'), 'Combined specification')
13+
readonly yamlBtn = new RadioButton(this.rootLocator.locator('input[type="radio"][value="yaml"]'), 'YAML')
14+
readonly jsonBtn = new RadioButton(this.rootLocator.locator('input[type="radio"][value="json"]'), 'JSON')
15+
readonly htmlBtn = new RadioButton(this.rootLocator.locator('input[type="radio"][value="html"]'), 'Interactive HTML')
16+
readonly preserveBtn = new RadioButton(this.rootLocator.locator('input[type="radio"][value="preserve"]'), 'Preserve all OAS extensions')
17+
readonly removeBtn = new RadioButton(this.rootLocator.locator('input[type="radio"][value="remove"]'), 'Remove OAS extensions')
18+
readonly exportBtn = new Button(this.rootLocator.getByTestId('ExportButton'), 'Export')
19+
readonly closeBtn = new Button(this.rootLocator.getByTestId('CloseButton'), 'Close')
20+
readonly infoIcon = new Icon(this.rootLocator.getByTestId('InfoIcon'), 'Info')
21+
22+
constructor(protected readonly page: Page) {
23+
super(page)
24+
}
25+
26+
async fillForm(params: ExportParams): Promise<void> {
27+
const { specType, fileFormat, OasExtensions } = params
28+
if (specType) {
29+
await report.step(`Set Specification type with "${specType}"`, async () => {
30+
switch (specType) {
31+
case 'reduced': {
32+
await this.reducedBtn.click()
33+
break
34+
}
35+
case 'combined': {
36+
await this.combinedBtn.click()
37+
break
38+
}
39+
}
40+
})
41+
}
42+
if (fileFormat) {
43+
await report.step(`Set File format with "${fileFormat}"`, async () => {
44+
switch (fileFormat) {
45+
case 'yaml': {
46+
await this.yamlBtn.click()
47+
break
48+
}
49+
case 'json': {
50+
await this.jsonBtn.click()
51+
break
52+
}
53+
case 'html': {
54+
await this.htmlBtn.click()
55+
break
56+
}
57+
}
58+
})
59+
}
60+
if (OasExtensions) {
61+
await report.step(`Set OpenAPI extensions with "${OasExtensions}"`, async () => {
62+
switch (OasExtensions) {
63+
case 'preserve': {
64+
await this.preserveBtn.click()
65+
break
66+
}
67+
case 'remove': {
68+
await this.removeBtn.click()
69+
break
70+
}
71+
}
72+
})
73+
}
74+
}
75+
76+
async performExport(): Promise<DownloadedTestFile> {
77+
let file!: DownloadedTestFile
78+
await report.step('Export', async () => {
79+
const downloadPromise = this.page.waitForEvent('download', { timeout: PUBLISH_TIMEOUT })
80+
await this.exportBtn.click()
81+
const download = await downloadPromise
82+
file = await getDownloadedFile(download)
83+
})
84+
return file
85+
}
86+
}
87+
88+
export type ExportParams = {
89+
specType?: 'reduced' | 'combined'
90+
fileFormat?: 'yaml' | 'json' | 'html'
91+
OasExtensions?: 'preserve' | 'remove'
92+
}

src/packages/portal/pages/PortalPage/VersionPage/DocumentPreviewPage/DocumentPreviewPageToolbar.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Page } from '@playwright/test'
22
import { Breadcrumbs, Button, Title } from '@shared/components/base'
3-
import { OpenapiDownloadMenu } from '../OpenapiDownloadMenu'
3+
import { DocumentsActionMenu } from '@portal/pages/PortalPage/VersionPage/VersionPackagePage/DocumentsPackageTab/DocumentsActionMenu'
44

55
export class DocumentPreviewPageToolbar {
66

@@ -12,7 +12,7 @@ export class DocumentPreviewPageToolbar {
1212
readonly detailedBtn = new Button(this.page.locator('button[value=detailed]'), 'Detailed')
1313
readonly docBtn = new Button(this.page.locator('button[value=doc]'), 'Doc')
1414
readonly rawBtn = new Button(this.page.locator('button[value=raw]'), 'Raw')
15-
readonly exportDocumentMenu = new OpenapiDownloadMenu(this.page.getByTestId('ExportDocumentMenuButton'), 'Export')
15+
readonly moreMenu = new DocumentsActionMenu(this.page.getByTestId('ExportDocumentMenuButton'), 'More')
1616

1717
constructor(protected readonly page: Page) { }
1818
}

src/packages/portal/pages/PortalPage/VersionPage/OpenapiDownloadMenu.ts

Lines changed: 0 additions & 72 deletions
This file was deleted.
Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import type { Locator } from '@playwright/test'
2-
import { type BaseComponent, Button, TableCell, TableRow } from '@shared/components/base'
3-
import { GroupDownloadMenu } from './OverviewGroupRow/GroupDownloadMenu'
2+
import { Button, TableCell, TableRow } from '@shared/components/base'
43
import { test as report } from 'playwright/test'
5-
import type { DownloadedTestFile } from '@shared/entities'
64
import { GroupNameCell } from './OverviewGroupRow/GroupNameCell'
7-
import { getDownloadedFile } from '@services/utils'
85

96
export class OverviewGroupRow extends TableRow {
107

@@ -15,8 +12,8 @@ export class OverviewGroupRow extends TableRow {
1512
readonly operationsNumberCell = new TableCell(this.mainLocator.getByTestId('Cell-operations-number'), this.componentName, 'operations number cell')
1613
readonly addBtn = new Button(this.mainLocator.getByTestId('AddButton'), this.componentName, 'add button')
1714
readonly editBtn = new Button(this.mainLocator.getByTestId('EditButton'), this.componentName, 'edit button')
15+
readonly exportBtn = new Button(this.mainLocator.getByTestId('ExportButton'), this.componentName, 'export button')
1816
readonly deleteBtn = new Button(this.mainLocator.getByTestId('DeleteButton'), this.componentName, 'delete button')
19-
readonly downloadMenu = new GroupDownloadMenu(this.mainLocator)
2017

2118
constructor(rootLocator: Locator, componentName?: string, componentType?: string) {
2219
super(rootLocator, componentName, componentType || 'group row')
@@ -36,44 +33,17 @@ export class OverviewGroupRow extends TableRow {
3633
})
3734
}
3835

39-
async openDeleteGroupDialog(): Promise<void> {
40-
await report.step(`Open "Delete group" dialog for the "${this.componentName}" group`, async () => {
36+
async openExportDialog(): Promise<void> {
37+
await report.step(`Open "Export settings" dialog for the "${this.componentName}" group`, async () => {
4138
await this.hover()
42-
await this.deleteBtn.click()
39+
await this.exportBtn.click()
4340
})
4441
}
4542

46-
async downloadCombinedYaml(): Promise<DownloadedTestFile> {
47-
return await this.hoverableDownload(this.mainLocator, 'Download combined YAML', this.downloadMenu, this.downloadMenu.combinedYamlItm)
48-
}
49-
50-
async downloadCombinedJson(): Promise<DownloadedTestFile> {
51-
return await this.hoverableDownload(this.mainLocator, 'Download combined JSON', this.downloadMenu, this.downloadMenu.combinedJsonItm)
52-
}
53-
54-
async downloadReducedYaml(): Promise<DownloadedTestFile> {
55-
return await this.hoverableDownload(this.mainLocator, 'Download reduced YAML', this.downloadMenu, this.downloadMenu.reducedYamlItm)
56-
}
57-
58-
async downloadReducedJson(): Promise<DownloadedTestFile> {
59-
return await this.hoverableDownload(this.mainLocator, 'Download reduced JSON', this.downloadMenu, this.downloadMenu.reducedJsonItm)
60-
}
61-
62-
async downloadReducedHtml(): Promise<DownloadedTestFile> {
63-
return await this.hoverableDownload(this.mainLocator, 'Download reduced HTML', this.downloadMenu, this.downloadMenu.reducedHtmlItm)
64-
}
65-
66-
//TODO: need to move to shared functions
67-
private async hoverableDownload(hoverableElement: Locator, stepTitle: string, menu: BaseComponent, menuElement: BaseComponent): Promise<DownloadedTestFile> {
68-
let file!: DownloadedTestFile
69-
await report.step(stepTitle, async () => {
70-
const downloadPromise = hoverableElement.page().waitForEvent('download')
71-
await hoverableElement.hover()
72-
await menu.click()
73-
await menuElement.click({ position: { x: 1, y: 1 } }) //WA: tooltip handling
74-
const download = await downloadPromise
75-
file = await getDownloadedFile(download)
43+
async openDeleteGroupDialog(): Promise<void> {
44+
await report.step(`Open "Delete group" dialog for the "${this.componentName}" group`, async () => {
45+
await this.hover()
46+
await this.deleteBtn.click()
7647
})
77-
return file
7848
}
7949
}

src/packages/portal/pages/PortalPage/VersionPage/VersionOverviewTab/OverviewGroupsTab/OverviewGroupRow/GroupDownloadMenu.ts

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/packages/portal/pages/PortalPage/VersionPage/VersionPackagePage/DocumentsPackageTab.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
import type { Page } from '@playwright/test'
22
import { DocumentsPackageTabSidebar } from './DocumentsPackageTab/DocumentsPackageTabSidebar'
3-
import { DocumentsMdView } from './DocumentsPackageTab/DocumentsPackageTabViews/DocumentsMdView'
4-
import { DocumentsJsonSchemaView } from './DocumentsPackageTab/DocumentsPackageTabViews/DocumentsJsonSchemaView'
5-
import { DocumentsFileView } from './DocumentsPackageTab/DocumentsPackageTabViews/DocumentsFileView'
6-
import { DocumentsOpenapiView } from './DocumentsPackageTab/DocumentsPackageTabViews/DocumentsOpenapiView'
7-
import { Content, Tab } from '@shared/components/base'
3+
import { DocumentsFileView } from './DocumentsPackageTab/DocumentsFileView'
4+
import { DocumentsOasView } from './DocumentsPackageTab/DocumentsOasView'
5+
import { Tab } from '@shared/components/base'
6+
import { DocumentsViewToolbar } from './DocumentsPackageTab/DocumentsViewToolbar'
7+
import { JsonSchemaView, MdView } from '@shared/components/custom'
88

99
export class DocumentsPackageTab extends Tab {
1010

1111
readonly mainLocator = this.page.getByTestId('DocumentsButton')
12-
readonly content = new Content(this.rootLocator, 'Documents Tab')
12+
readonly toolbar = new DocumentsViewToolbar(this.page)
1313
readonly sidebar = new DocumentsPackageTabSidebar(this.page)
14-
readonly openapiView = new DocumentsOpenapiView(this.page)
15-
readonly mdView = new DocumentsMdView(this.page)
16-
readonly jsonSchemaView = new DocumentsJsonSchemaView(this.page)
14+
readonly oasView = new DocumentsOasView(this.page)
15+
readonly jsonSchemaView = new JsonSchemaView(this.page)
16+
readonly mdView = new MdView(this.page)
1717
readonly fileView = new DocumentsFileView(this.page)
1818

1919
constructor(page: Page) {
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { type Locator, test as report } from '@playwright/test'
2+
import { DropdownMenu, ListItem } from '@shared/components/base'
3+
import { MenuItem } from '@shared/components/base/list-items/MenuItem'
4+
import { PUBLISH_TIMEOUT } from '@test-setup'
5+
import type { DownloadedTestFile } from '@shared/entities'
6+
import { getDownloadedFile } from '@services/utils'
7+
8+
export class DocumentsActionMenu extends DropdownMenu {
9+
10+
readonly componentType: string = 'action menu'
11+
12+
readonly previewItm = new MenuItem(this.page.getByTestId('PreviewMenuItem'), 'Preview')
13+
readonly exportItm = new MenuItem(this.page.getByTestId('ExportMenuItem'), 'Export')
14+
readonly downloadItm = new MenuItem(this.page.getByTestId('DownloadMenuItem'), 'Download')
15+
readonly copyPublicLinkItm = new ListItem(this.page.getByTestId('CopyPublicLinkMenuItem'), 'Copy public link to source')
16+
readonly copyPageTemplateItm = new ListItem(this.page.getByTestId('CopyPageTemplateMenuItem'), 'Copy page template')
17+
18+
constructor(rootLocator: Locator, componentName?: string, componentType?: string) {
19+
super(rootLocator, componentName, componentType)
20+
}
21+
22+
async performDownload(): Promise<DownloadedTestFile> {
23+
let file!: DownloadedTestFile
24+
await report.step('Download', async () => {
25+
const downloadPromise = this.page.waitForEvent('download', { timeout: PUBLISH_TIMEOUT })
26+
await this.downloadItm.click()
27+
const download = await downloadPromise
28+
file = await getDownloadedFile(download)
29+
})
30+
return file
31+
}
32+
33+
async copyPublicLink(): Promise<string> {
34+
let str = ''
35+
await report.step('Copy public link to source', async () => {
36+
await this.copyPublicLinkItm.click()
37+
await this.page.waitForTimeout(2000)
38+
str = await this.mainLocator.evaluate('navigator.clipboard.readText()')
39+
})
40+
return str
41+
}
42+
43+
async copyPageTemplate(): Promise<string> {
44+
let str = ''
45+
await report.step('Copy page template', async () => {
46+
await this.copyPageTemplateItm.click()
47+
await this.page.waitForTimeout(2000)
48+
str = await this.mainLocator.evaluate('navigator.clipboard.readText()')
49+
})
50+
return str
51+
}
52+
}

0 commit comments

Comments
 (0)