From 4a877d079c4a41c406f51aec9453d47fb130c80d Mon Sep 17 00:00:00 2001 From: step21 Date: Wed, 20 Mar 2024 21:55:00 +0100 Subject: [PATCH] adding pageobjects and github ci workflow --- .github/workflows/e2e.yml | 27 ++++++++++++ tests/basicTests.js | 68 +++++++++++++++++++++++++++++ tests/pageobjects/agreement.page.js | 18 ++++++++ tests/pageobjects/apply.page.js | 65 +++++++++++++++++++++++++++ tests/pageobjects/copyright.page.js | 36 +++++++++++++++ tests/pageobjects/general.page.js | 21 +++++++++ tests/pageobjects/page.js | 46 +++++++++++++++++++ tests/pageobjects/patents.page.js | 17 ++++++++ tests/pageobjects/review.page.js | 26 +++++++++++ 9 files changed, 324 insertions(+) create mode 100644 .github/workflows/e2e.yml create mode 100644 tests/basicTests.js create mode 100644 tests/pageobjects/agreement.page.js create mode 100644 tests/pageobjects/apply.page.js create mode 100644 tests/pageobjects/copyright.page.js create mode 100644 tests/pageobjects/general.page.js create mode 100644 tests/pageobjects/page.js create mode 100644 tests/pageobjects/patents.page.js create mode 100644 tests/pageobjects/review.page.js diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 0000000..11e31bd --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,27 @@ +name: Webdriverio tests + +on: + push: + branches: ["main", "webdriverio"] + pull_request: + branches: ["main", "webdriverio"] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18.x, 20.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + - run: npm ci + - run: npm run build --if-present + - run: npm run serve-and-test diff --git a/tests/basicTests.js b/tests/basicTests.js new file mode 100644 index 0000000..f35f1f7 --- /dev/null +++ b/tests/basicTests.js @@ -0,0 +1,68 @@ +//const { expect } = require('@wdio/globals'); +//const page = require('./pageobjects/page.js') +const Page = require('./pageobjects/page'); +//const generalpage = require('./pageobjects/general.page') +const { expect } = require('chai'); +const page = new Page(); + + +describe('Basic Page load testing', function() { + // maybe change to beforeEach? + //before(async function() { + // await browser.url('http://localhost:4000/'); + //}); + + //it('should load the page correctly', async function() { + it('should show the right title', async function() { + await page.open(); + const title = await page.pageTitle; + // expect... ? + //await expect(title).toBeExisting(); + expect(title).to.include('Contributor License Agreement Chooser') +// await expect(title).toHaveTextContaining('Contributor License Agreement Chooser') + }); + it('should get and log the url', async function() { + const url = page.pageUrl; + await console.log(url); + await expect(url).to.exist; + //expect(url). + }); + + // }); +}); + +// chai does not allow for arrow functions because of some binding of the test +describe('Contributoragreements.org tests', function() { + before(async function() { + await browser.url('https://contributoragreements.org/ca-cla-chooser/'); + }); + + it('should show contributoragreements title', async function () { + let title2 = await browser.getTitle(); + //await expect(title2).toBeExisting(); + await expect(title2).equal('Contributor License Agreement Chooser'); + }); + +}); + +/*describe('DuckDuckGo search', function() { + + before(async function() { + await browser.url('https://duckduckgo.com'); + }); + it('Searches for WebdriverIO', async () => { + await browser.url('https://duckduckgo.com/?t=h_&q=WebdriverIO&ia=web') + +// await driver.findElement(By.id("search_form_input")).sendKeys('WebdriverIO'); //, Key.RETURN); + //await driver.findElement(By.id("searchbox_input")).sendKeys(Keys.ENTER); + await $('#search_button').click(); + + let title = await browser.getTitle() + expect(title).to.equal('WebdriverIO at DuckDuckGo') + // or just + //await expect(driver).toHaveTitle('WebdriverIO at DuckDuckGo') + }); + +})*/ + + diff --git a/tests/pageobjects/agreement.page.js b/tests/pageobjects/agreement.page.js new file mode 100644 index 0000000..bb068e3 --- /dev/null +++ b/tests/pageobjects/agreement.page.js @@ -0,0 +1,18 @@ +// apply.page.js +import ApplyPage from './apply.page' + +class AgreementPage extends ApplyPage { + + get agreementFlaTitle () { this.applyResultHtmlFlaText() } + //get agreementFlaSubtitle + + //get applyResultHtmFlaText () { return $('#embed-agreement-fla') } + + //get applyResultMkdnFlaText () { return $('#embed-agreement-fla-mkdn') } + //get applyResultHtmlFlaEntityText () { return $('#embed-agreement-fla-entity') } + //get applyResultMkdnFlaEntityText () { return $('#embed-agreement-fla-entity-mkdn') } + + +} +module.exports = new AgreementPage() +//export default new AgreementPage() diff --git a/tests/pageobjects/apply.page.js b/tests/pageobjects/apply.page.js new file mode 100644 index 0000000..19aaf9d --- /dev/null +++ b/tests/pageobjects/apply.page.js @@ -0,0 +1,65 @@ +// apply.page.js +import Page from './page' + +class ApplyPage extends Page { + + // get fla text fields + get textAgreementNameFiduciary () { return $('#apply-fla td').selectByVisibleText('Fiduciary Contributor License Agreement') } + get textAgreementVersionFiduciary () { return $('#apply-fla td').selectByVisibleText('Fiduciary License Agreement 2.0') } + get textAgreementNameEntityFiduciary () { return $('#apply-fla-entity td').selectByVisibleText('Enity Fiduciary Contributor License Agreement') } + get textAgreementVersionEntityFiduciary () { return $('#apply-fla-entity td').selectByVisibleText('Fiduciary License Agreement 2.0') } + // get custom cla text fields + get textAgreementNameIndividual () { return $('#apply-individual td').selectByVisibleText('Individual Contributor License Agreement') } + get textAgreementVersionIndividual () { return $('#apply-individual td').selectByVisibleText('Contributor Agreements 1.1') } + get textAgreementNameEntity () { return $('#apply-entity td').selectByVisibleText('Entity Contributor License Agreement') } + get textAgreementVersionEntity () { return $('#apply-entity td').selectByVisibleText('ContributorAgreements 1.1') } + + // TODO maybe add additional fields for parts of the actual agreement or preferably do that as a sub-page + // get fla format fields and content + get applyResultLinkFla () { return $('#btn-link-fla-indv') } + get applyResultLinkFlaText () { return this.applyResultLinkFla.getAttribute('href') } + get applyResultLinkFlaEntity () { return $('#btn-link-fla-entity') } + get applyResultLinkFlaEntityText () { return this.applyResultLinkFlaEntity.getAttribute('href') } + get applyResultHtmlFlaBtn () { return $('[href="#myHTML-fla"]') } + // inconsistency: html version does not have the format (html) in the id + get applyResultHtmlFlaText () { return $('#embed-agreement-fla') } + get applyResultMkdnFlaBtn () { return $('[href="#myMKDN-fla"]') } + get applyResultMkdnFlaText () { return $('#embed-agreement-fla-mkdn') } + get applyResultHtmlFlaEntityBtn () { return $('[href="#myHTML-fla-entity"]') } + get applyResultHtmlFlaEntityText () { return $('#embed-agreement-fla-entity') } + get applyResultMkdnFlaEntityBtn () { return $('[href="#myMKDN-fla-entity"]') } + get applyResultMkdnFlaEntityText () { return $('#embed-agreement-fla-entity-mkdn') } + // TODO / Not really sure if accessing the correct text needs to have the button clicked first (i.e. what triggers replacement, though I think it is either always instant or happens on going to the review or apply tab) + async openHtmlFla () { await this.applyResultHtmlFlaBtn.click() } + async openMkdnFla () { await this.applyResultMkdnFlaBtn.click() } + async openHtmlFlaEntity () { await this.applyResultHtmlFlaEntityBtn.click() } + async openMkdnFlaEntity () { await this.applyResultMkdnFlaEntityBtn.click() } + + //get applyResultPdfFla + + // get custom cla format fields and content + get applyResultLinkCla () { return $('#btn-link-cla-indv') } + get applyResultLinkClaText () { return this.applyResultLinkCla.getAttribute('href') } + get applyResultLinkClaEntity () { return $('#btn-link-cla-entity') } + get applyResultLinkClaEntityText () { return this.applyResultLinkClaEntity.getAttribute('href') } + get applyResultHtmlClaBtn () { return $('[href=#myHTML]') } + get applyResultHtmlClaText () { return $('#embed-agreement') } + get applyResultMkdnClaBtn () { return $('[href=#myMKDN]') } + get applyResultMkdnClaText () { return $('#embed-agreement-mkdn') } + // get applyResultPdfCla + get applyResultHtmlClaEntityBtn () { return $('[href=#myHTML-entity]') } + get applyResultHtmlClaEntityText () { return $('#embed-agreement-entity') } + get applyResultMkdnClaEntityBtn () { return $('[href=#myMKDN-entity]') } + get applyResultMkdnClaEntityText () { return $('#embed-agreement-entity-mkdn') } + // get e-signing content + get applyLinkEsign () { $('#link-esign').getAttribute('href') } + get applyEmbedCodeEsign () { $('#embed-esign') } + get applyEmbedCodeEsignValue () { this.applyEmbedCodeEsign.getValue() } + async openHtmlCla () { await this.applyResultHtmlClaBtn.click() } + async openMkdnCla () { await this.applyResultMkdnClaBtn.click() } + async openHtmlClaEntity () { await this.applyResultHtmlClaEntityBtn.click() } + async openMkdnClaEntity () { await this.applyResultMkdnClaEntityBtn.click() } +} + +module.exports = new ApplyPage() +//export default new ApplyPage() diff --git a/tests/pageobjects/copyright.page.js b/tests/pageobjects/copyright.page.js new file mode 100644 index 0000000..767310b --- /dev/null +++ b/tests/pageobjects/copyright.page.js @@ -0,0 +1,36 @@ +// copyright.page.js +import Page from './page' + +class CopyrightPage extends Page { + + // fsfe copyright options + get optionOutboundFsf () { return $('#outbound-option-fsfe') } + get optionOutboundListedLicenses () { return $('#outbound-option-same-licenses') } + get sameLicensesList () { return $('#outboundlist') } + get sameLicensesText () { return $('#outboundlist-custom') } + get optionOutboundLicensePolicy () { return $('#outbound-option-license-policy') } + get fieldLicensePolicyLocation () { return $('#license-policy-location') } + // extra options for non-fsfe + get optionOutboundSameOnDate () { return $('#outbound-option-same') } + get optionOutboundNoCommitment () { return $('#outbound-option-no-commitment') } + get optionDocumentationLicense () { return $('#medialist') } + + async selectOutboundFsf () { + await this.optionOutboundFsf.click() + } + async selectOutboundListedLicenses () { + await this.optionOutboundListedLicenses.click() + } + async selectOutboundLicensePolicy () { + await this.optionOutboundLicensePolicy.click() + } + async selectOutboundSameOnDate () { + await this.optionOutboundSameOnDate.click() + } + async selectOutboundNoCommitment () { + await this.optionOutboundNoCommitment.click() + } +} + +module.exports = new CopyrightPage() +//export default new CopyrightPage() diff --git a/tests/pageobjects/general.page.js b/tests/pageobjects/general.page.js new file mode 100644 index 0000000..8ce4d42 --- /dev/null +++ b/tests/pageobjects/general.page.js @@ -0,0 +1,21 @@ +// general.page.js +const { $ } = require('@wdio/globals') +const Page = require('./page') +//import Page from './page' + +class GeneralPage extends Page { + + get btnFsfeCompliance () { return $('#fsfe-compliance') } + get btnNonFsfeCompliance () { '#non-fsfe-compliance' } + get fieldBeneficiaryName () { '#beneficiary-name' } + get fieldProjectName () { '#project-name' } + get fieldProjectWebsite () { '#project-website' } + get fieldProjectEmail () { '#project-email' } + get fieldContributorSigningProcessWebsite () { '#contributor-process-url' } + get fieldJurisdiction () { '#project-jurisdiction' } + + +} + +module.exports = new GeneralPage() +//export default new GeneralPage() diff --git a/tests/pageobjects/page.js b/tests/pageobjects/page.js new file mode 100644 index 0000000..5cbabae --- /dev/null +++ b/tests/pageobjects/page.js @@ -0,0 +1,46 @@ +const { browser } = require('@wdio/globals') +// Page.js + +module.exports = class Page { +//export default class Page { + + get pageTitle () { return browser.getTitle() } + get pageUrl () { return browser.getUrl() } + + get navBullets () { return $('ul .bullets') } + get generalBullet () { return $('#generalBullet') } + get copyrightBullet () { return $('#copyrightBullet') } + get patentsBullet () { return $('#patentsBullet') } + get reviewBullet () { return $('#reviewBullet') } + get applyBullet () { return $('#applyBullet') } + + get nextBtn () { return $('.next a') } + get previousBtn () { return $('.previous a') } + + open (path = '') { + return browser.url(`http://localhost:4000${path}`) + } + async next () { + await this.nextBtn.click() + } + async previous () { + await this.previousBtn.click() + } + async gotoGeneral () { + await this.generalBullet.click() + } + async gotoCopyright () { + await this.copyrightBullet.click() + } + async gotoPatents () { + await this.patentsBullet.click() + } + async gotoReview () { + await this.reviewBullet.click() + } + async gotoApply () { + await this.applyBullet.click() + } +} + + diff --git a/tests/pageobjects/patents.page.js b/tests/pageobjects/patents.page.js new file mode 100644 index 0000000..6326286 --- /dev/null +++ b/tests/pageobjects/patents.page.js @@ -0,0 +1,17 @@ +// patents.page.js +import Page from './page' + +class PatentsPage extends Page { + + // non-fsfe patent options + get patentType () { return $('#patent-option') } + get patentLicense () {return this.patentType.selectByVisibleText('Traditional Patent License') } + get patentPledge () {return this.patentType.selectByVisibleText('Identified Patent Pledge') } + async selectPatentOption () { + await this.patentType.click() + } + +} + +module.exports = new PatentsPage() +//export default new PatentsPage() diff --git a/tests/pageobjects/review.page.js b/tests/pageobjects/review.page.js new file mode 100644 index 0000000..3f313c7 --- /dev/null +++ b/tests/pageobjects/review.page.js @@ -0,0 +1,26 @@ +// review.page.js +import Page from './page' + +class ReviewPage extends Page { + + // review page + get reviewBeneficiaryName () { return $('#review-beneficiary-name') } + get reviewProjectName () { return $('#review-project-name') } + get reviewProjectWebsite () { return $('#review-project-website') } + get reviewProjectEmail () { return $('#review-project-email') } + get reviewProjectSigningProcessAddress () { return $('#review-contributor-process-url') } + get reviewProjectJurisdiction () {return $('#review-project-jurisdiction') } + get reviewAgreementExclusivity () { return $('#review-agreement-exclusivity') } + get reviewOutboundLicenses () { return $('#review-outbound-licenses') } + // no media licenses for fsfe fla - (and why is it called 'line' at the end? + get reviewMediaLicenses () { return $('#review-media-licenses-line') } + get reviewPatentType () { return $('#review-patent-type') } + get reviewTextFla () { return $('#review-text-fla') } + get reviewTextFlaEntity () { return $('#review-text-fla-entity') } + // get non-fsfe review Texts + get reviewText () { return $('#review-text') } + get reviewTextEntity () { return $('#review-text-entity' ) } +} + +module.exports = new ReviewPage() +//export default new ReviewPage()