From 0d1ba6a28aa81dfd3b12de72b8437298b15497a7 Mon Sep 17 00:00:00 2001
From: Alex Velichko <nestor_007@mail.ru>
Date: Tue, 17 Oct 2023 12:58:56 +0300
Subject: [PATCH] feat(tests): added page-object model example. Refactor login
 test to page-object model. Added a new test channel.spec.ts (#3847)

* feat(tests): added page-object model example. Refactor login test to page-object model. Added a new test channel.spec.ts
---------

Signed-off-by: Alex Velichko <nestor_007@mail.ru>
---
 tests/readme.md                               |  2 +-
 tests/sanity/tests/channel.spec.ts            | 32 ++++++++++++++++++
 tests/sanity/tests/login.spec.ts              | 30 +++++------------
 tests/sanity/tests/model/channel-page.ts      | 24 ++++++++++++++
 tests/sanity/tests/model/chunter-page.ts      | 33 +++++++++++++++++++
 .../sanity/tests/model/left-side-menu-page.ts | 13 ++++++++
 tests/sanity/tests/model/login-page.ts        | 29 ++++++++++++++++
 .../tests/model/select-workspace-page.ts      | 15 +++++++++
 8 files changed, 156 insertions(+), 22 deletions(-)
 create mode 100644 tests/sanity/tests/channel.spec.ts
 create mode 100644 tests/sanity/tests/model/channel-page.ts
 create mode 100644 tests/sanity/tests/model/chunter-page.ts
 create mode 100644 tests/sanity/tests/model/left-side-menu-page.ts
 create mode 100644 tests/sanity/tests/model/login-page.ts
 create mode 100644 tests/sanity/tests/model/select-workspace-page.ts

diff --git a/tests/readme.md b/tests/readme.md
index 7eca491791..2665a0403f 100644
--- a/tests/readme.md
+++ b/tests/readme.md
@@ -18,7 +18,7 @@ To purge content of sanity workspace following command could be used.
 ./restore-workspace.sh
 ```
 
-## Prepare local dev enviornment
+## Prepare local dev environment
 
 ```bash
 rush update
diff --git a/tests/sanity/tests/channel.spec.ts b/tests/sanity/tests/channel.spec.ts
new file mode 100644
index 0000000000..913c4113c1
--- /dev/null
+++ b/tests/sanity/tests/channel.spec.ts
@@ -0,0 +1,32 @@
+import { test } from '@playwright/test'
+import { generateId, PlatformSetting, PlatformURI } from './utils'
+import { LeftSideMenuPage } from './model/left-side-menu-page'
+import { ChunterPage } from './model/chunter-page'
+import { ChannelPage } from './model/channel-page'
+
+test.use({
+  storageState: PlatformSetting
+})
+
+test.describe('channel tests', () => {
+  test.beforeEach(async ({ page }) => {
+    await (await page.goto(`${PlatformURI}/workbench/sanity-ws`))?.finished()
+  })
+
+  test('create new private channel tests', async ({ page }) => {
+    const leftSideMenuPage = new LeftSideMenuPage(page)
+    await leftSideMenuPage.buttonChunter.click()
+
+    const chunterPage = new ChunterPage(page)
+    await chunterPage.buttonChannelBrowser.click()
+    await chunterPage.buttonNewChannelHeader.click()
+
+    const channel = 'channel-' + generateId()
+    await chunterPage.createNewChannel(channel, true)
+    await chunterPage.openChannel(channel)
+
+    const channelPage = new ChannelPage(page)
+    await channelPage.sendMessage('Test message')
+    await channelPage.checkMessageExist('Test message')
+  })
+})
diff --git a/tests/sanity/tests/login.spec.ts b/tests/sanity/tests/login.spec.ts
index 67ece1f9d0..02d66e19ae 100644
--- a/tests/sanity/tests/login.spec.ts
+++ b/tests/sanity/tests/login.spec.ts
@@ -1,5 +1,7 @@
-import { expect, test } from '@playwright/test'
-import { PlatformURI, PlatformUser } from './utils'
+import { test } from '@playwright/test'
+import { PlatformUser } from './utils'
+import { LoginPage } from './model/login-page'
+import { SelectWorkspacePage } from './model/select-workspace-page'
 
 test.describe('login test', () => {
   test('check login', async ({ page }) => {
@@ -7,25 +9,11 @@ test.describe('login test', () => {
       console.log('Uncaught exception:')
       console.log(exception.message)
     })
+    const loginPage = new LoginPage(page)
+    await loginPage.goto()
+    await loginPage.login(PlatformUser, '1234')
 
-    // Create user and workspace
-    await (
-      await page.goto(`${PlatformURI}/login/login`)
-    )?.finished
-
-    const emaillocator = page.locator('[name=email]')
-    await emaillocator.click()
-    await emaillocator.fill(PlatformUser)
-
-    const password = page.locator('[name=current-password]')
-    await password.click()
-    await password.fill('1234')
-
-    const button = page.locator('button:has-text("Log In")')
-    expect(await button.isEnabled()).toBe(true)
-
-    await button.click()
-
-    await page.click('text=sanity-ws')
+    const selectWorkspacePage = new SelectWorkspacePage(page)
+    await selectWorkspacePage.selectWorkspace('sanity-ws')
   })
 })
diff --git a/tests/sanity/tests/model/channel-page.ts b/tests/sanity/tests/model/channel-page.ts
new file mode 100644
index 0000000000..df7b3f6463
--- /dev/null
+++ b/tests/sanity/tests/model/channel-page.ts
@@ -0,0 +1,24 @@
+import { expect, type Locator, type Page } from '@playwright/test'
+
+export class ChannelPage {
+  readonly page: Page
+  readonly inputMessage: Locator
+  readonly buttonSendMessage: Locator
+  readonly textMessage: Locator
+
+  constructor (page: Page) {
+    this.page = page
+    this.inputMessage = page.locator('div[class~="text-editor-view"]')
+    this.buttonSendMessage = page.locator('g#Send')
+    this.textMessage = page.locator('div.message > div.text')
+  }
+
+  async sendMessage (message: string): Promise<void> {
+    await this.inputMessage.fill(message)
+    await this.buttonSendMessage.click()
+  }
+
+  async checkMessageExist (message: string): Promise<void> {
+    await expect(await this.textMessage.filter({ hasText: message })).toBeVisible()
+  }
+}
diff --git a/tests/sanity/tests/model/chunter-page.ts b/tests/sanity/tests/model/chunter-page.ts
new file mode 100644
index 0000000000..d2ef97799f
--- /dev/null
+++ b/tests/sanity/tests/model/chunter-page.ts
@@ -0,0 +1,33 @@
+import { type Locator, type Page } from '@playwright/test'
+
+export class ChunterPage {
+  readonly page: Page
+  readonly buttonChannelBrowser: Locator
+  readonly buttonNewChannelHeader: Locator
+  readonly inputNewChannelName: Locator
+  readonly checkboxMakePrivate: Locator
+  readonly buttonCreateChannel: Locator
+  readonly buttonOpenChannel: Locator
+
+  constructor (page: Page) {
+    this.page = page
+    this.buttonChannelBrowser = page.locator('span', { hasText: 'Channel browser' })
+    this.buttonNewChannelHeader = page.locator('div[class~="ac-header"] button span', { hasText: 'New Channel' })
+    this.inputNewChannelName = page.locator('form.antiCard input[type="text"]')
+    this.checkboxMakePrivate = page.locator('span.toggle-switch')
+    this.buttonCreateChannel = page.locator('button[type="submit"] span', { hasText: 'Create' })
+    this.buttonOpenChannel = page.locator('div.antiNav-element__dropbox span.overflow-label')
+  }
+
+  async createNewChannel (channelName: string, privateChannel: boolean): Promise<void> {
+    await this.inputNewChannelName.fill(channelName)
+    if (privateChannel) {
+      await this.checkboxMakePrivate.click()
+    }
+    await this.buttonCreateChannel.click()
+  }
+
+  async openChannel (channelName: string): Promise<void> {
+    await this.buttonOpenChannel.filter({ hasText: channelName }).click()
+  }
+}
diff --git a/tests/sanity/tests/model/left-side-menu-page.ts b/tests/sanity/tests/model/left-side-menu-page.ts
new file mode 100644
index 0000000000..65ba39fc65
--- /dev/null
+++ b/tests/sanity/tests/model/left-side-menu-page.ts
@@ -0,0 +1,13 @@
+import { type Locator, type Page } from '@playwright/test'
+
+export class LeftSideMenuPage {
+  readonly page: Page
+  readonly buttonChunter: Locator
+  readonly buttonContacts: Locator
+
+  constructor (page: Page) {
+    this.page = page
+    this.buttonChunter = page.locator('button[id$="ApplicationLabelChunter"]')
+    this.buttonContacts = page.locator('button[id$="Contacts"]')
+  }
+}
diff --git a/tests/sanity/tests/model/login-page.ts b/tests/sanity/tests/model/login-page.ts
new file mode 100644
index 0000000000..5aa23fed51
--- /dev/null
+++ b/tests/sanity/tests/model/login-page.ts
@@ -0,0 +1,29 @@
+import { expect, type Locator, type Page } from '@playwright/test'
+import { PlatformURI } from '../utils'
+
+export class LoginPage {
+  readonly page: Page
+  readonly inputEmail: Locator
+  readonly inputPassword: Locator
+  readonly buttonLogin: Locator
+
+  constructor (page: Page) {
+    this.page = page
+    this.inputEmail = page.locator('input[name=email]')
+    this.inputPassword = page.locator('input[name=current-password]')
+    this.buttonLogin = page.locator('button', { hasText: 'Log In' })
+  }
+
+  async goto (): Promise<void> {
+    await (
+      await this.page.goto(`${PlatformURI}/login/login`)
+    )?.finished
+  }
+
+  async login (email: string, password: string): Promise<void> {
+    await this.inputEmail.fill(email)
+    await this.inputPassword.fill(password)
+    expect(await this.buttonLogin.isEnabled()).toBe(true)
+    await this.buttonLogin.click()
+  }
+}
diff --git a/tests/sanity/tests/model/select-workspace-page.ts b/tests/sanity/tests/model/select-workspace-page.ts
new file mode 100644
index 0000000000..55e5f38930
--- /dev/null
+++ b/tests/sanity/tests/model/select-workspace-page.ts
@@ -0,0 +1,15 @@
+import { type Locator, type Page } from '@playwright/test'
+
+export class SelectWorkspacePage {
+  readonly page: Page
+  readonly buttonWorkspace: Locator
+
+  constructor (page: Page) {
+    this.page = page
+    this.buttonWorkspace = page.locator('div[class*="workspace"]')
+  }
+
+  async selectWorkspace (workspace: string): Promise<void> {
+    await this.buttonWorkspace.filter({ hasText: workspace }).click()
+  }
+}