From cf0468ba14d0b7ddbe59472235ae945ec3440b68 Mon Sep 17 00:00:00 2001 From: kaplunova Date: Wed, 6 Nov 2024 01:18:26 +0200 Subject: [PATCH] added tests --- cypress/e2e/article.cy.js | 48 +++++++++++++++---- cypress/e2e/settings.cy.js | 35 ++++++++++---- cypress/e2e/signIn.cy.js | 7 +++ cypress/e2e/signUp.cy.js | 28 ++++++++++- cypress/e2e/user.cy.js | 27 +++++++++-- cypress/support/commands.js | 49 ++++++++++++++++++++ cypress/support/index.d.ts | 1 + cypress/support/pages/article.pageObject.js | 47 +++++++++++++++++++ cypress/support/pages/settings.pageObject.js | 47 +++++++++++++++++++ cypress/support/pages/signIn.pageObject.js | 5 ++ cypress/support/pages/signUp.pageObject.js | 48 +++++++++++++++++++ cypress/support/pages/user.pageObject.js | 32 +++++++++++++ src/vue/components/ArticleActions.vue | 4 +- src/vue/routes/ArticleEdit.vue | 4 ++ src/vue/routes/Home.vue | 1 + src/vue/routes/Profile.vue | 2 + src/vue/routes/Register.vue | 5 +- src/vue/routes/Settings.vue | 8 +++- 18 files changed, 368 insertions(+), 30 deletions(-) create mode 100644 cypress/support/pages/article.pageObject.js create mode 100644 cypress/support/pages/settings.pageObject.js create mode 100644 cypress/support/pages/signUp.pageObject.js create mode 100644 cypress/support/pages/user.pageObject.js diff --git a/cypress/e2e/article.cy.js b/cypress/e2e/article.cy.js index e1ef839b..860d0491 100644 --- a/cypress/e2e/article.cy.js +++ b/cypress/e2e/article.cy.js @@ -1,24 +1,52 @@ /// /// +import SignInPageObject from "../support/pages/signIn.pageObject"; +const signInPage = new SignInPageObject(); +import ArticlePageObject from "../support/pages/article.pageObject"; +const articlePage = new ArticlePageObject(); describe('Article', () => { - before(() => { - - }); - - beforeEach(() => { - cy.task('db:clear'); - }); + beforeEach(() => { + let user; + cy.task('db:clear'); + cy.task('generateUser').then((generateUser) => { + user = new Object(generateUser); + cy.login(user.email, user.username, user.password); + }); + articlePage.visit(); + }); it('should be created using New Article form', () => { - + cy.task('generateArticle').then((articleDataString) => { + const article = new Object(articleDataString); + articlePage.typeArticleTitle(article.title); + articlePage.typeArticleDesc(article.description); + articlePage.typeArticleBody(article.body); + articlePage.publishArticle(); + }); }); it('should be edited using Edit button', () => { - + cy.task('generateArticle').then((articleDataString) => { + const article = new Object(articleDataString); + cy.createArticle(article.title, article.description, article.body); + }); + articlePage.editArticle(); + cy.task('generateArticle').then((articleDataString) => { + const articleUpdated = new Object(articleDataString); + articlePage.typeArticleTitle(articleUpdated.title); + articlePage.typeArticleDesc(articleUpdated.description); + articlePage.typeArticleBody(articleUpdated.body); + }); + + articlePage.updateArticle(); }); it('should be deleted using Delete button', () => { - + cy.task('generateArticle').then((articleDataString) => { + const article = new Object(articleDataString); + cy.createArticle(article.title, article.description, article.body); + }); + articlePage.deleteArticle(); }); }); diff --git a/cypress/e2e/settings.cy.js b/cypress/e2e/settings.cy.js index e9208789..1121a325 100644 --- a/cypress/e2e/settings.cy.js +++ b/cypress/e2e/settings.cy.js @@ -1,32 +1,47 @@ /// /// +import SettingsPageObject from '../support/pages/settings.pageObject'; +const settingPage = new SettingsPageObject(); +const { faker } = require('@faker-js/faker'); +const testData = { + updateName: faker.person.firstName().toLowerCase(), + updateBio: faker.person.bio(), + updateEmail: faker.internet.email(), + updatePass: faker.internet.password({ length: 9 }) +}; describe('Settings page', () => { - before(() => { - - }); - + let user; beforeEach(() => { - + cy.task('db:clear'); + cy.task('generateUser').then((generateUser) => { + user = new Object(generateUser); + cy.login(user.email, user.username, user.password); + }); + settingPage.visit(); }); it('should provide an ability to update username', () => { - + settingPage.typeUsernameField(testData.updateName); + settingPage.updateSettings(); }); it('should provide an ability to update bio', () => { - + settingPage.typeBioField(testData.updateBio); + settingPage.updateSettings(); }); it('should provide an ability to update an email', () => { - + settingPage.typeEmailField(testData.updateEmail); + settingPage.updateSettings(); }); it('should provide an ability to update password', () => { - + settingPage.typePassField(testData.updatePass); + settingPage.updateSettings(); }); it('should provide an ability to log out', () => { - + settingPage.logoutFromSettings(); }); }); diff --git a/cypress/e2e/signIn.cy.js b/cypress/e2e/signIn.cy.js index 3ae60e04..27d1f790 100644 --- a/cypress/e2e/signIn.cy.js +++ b/cypress/e2e/signIn.cy.js @@ -29,6 +29,13 @@ describe('Sign In page', () => { }); it('should not provide an ability to log in with wrong credentials', () => { + signInPage.visit(); + cy.register(user.email, user.username, user.password); + + signInPage.typeEmail(user.email); + signInPage.typePassword('test123'); + signInPage.clickSignInBtn(); + signInPage.assertErrorMessage('email or password: is invalid'); }); }); diff --git a/cypress/e2e/signUp.cy.js b/cypress/e2e/signUp.cy.js index ccf57970..d1e4fa19 100644 --- a/cypress/e2e/signUp.cy.js +++ b/cypress/e2e/signUp.cy.js @@ -1,12 +1,36 @@ /// /// +import SignUpPageObject from "../support/pages/signUp.pageObject"; +const signUpPage = new SignUpPageObject(); +import HomePageObject from '../support/pages/home.pageObject'; +const homePage = new HomePageObject(); +const wrongEmail = 'test@gmail.com'; describe('Sign Up page', () => { - before(() => { + beforeEach(() => { + let user; + cy.task('db:clear'); + cy.task('generateUser').then((generateUser) => { + user = new Object(generateUser); + }); + signUpPage.visit(); + }); + + it('should sign up with valid credentials', () => { + signUpPage.typeEmail(user.email); + signUpPage.typeUsername(user.username); + signUpPage.typePassword(user.password); + signUpPage.clickSignUpBtn(); + homePage.assertHeaderContainUsername(user.username); }); - it('should ...', () => { + it('should not provide an ability to sign up in with wrong credentials', () => { + signUpPage.typeEmail(wrongEmail); + signUpPage.typeUsername(user.username); + signUpPage.typePassword(user.password); + signUpPage.clickSignUpBtn(); + signUpPage.assertErrorMessage('This email is taken.'); }); }); diff --git a/cypress/e2e/user.cy.js b/cypress/e2e/user.cy.js index 012f6fa7..646df88a 100644 --- a/cypress/e2e/user.cy.js +++ b/cypress/e2e/user.cy.js @@ -1,12 +1,33 @@ /// /// +import SignUpPageObject from "../support/pages/signUp.pageObject"; +import UserPageObject from "../support/pages/user.pageObject"; +import HomePageObject from '../support/pages/home.pageObject'; +const signUpPage = new SignUpPageObject(); +const homePage = new HomePageObject(); +const userPage = new UserPageObject(); describe('User', () => { - before(() => { - + beforeEach(() => { + let user; + cy.task('db:clear'); + cy.task('generateUser').then((generateUser) => { + user = new Object(generateUser); + }); + homePage.visit(); }); - it.skip('should be able to follow the another user', () => { + it('should be able to follow the another user', () => { + userPage.getGlobalFeed(); + userPage.goToProfile(); + userPage.followUser(); + userPage.pageHasUnfollowBtn(); + }); + it('should be able to unfollow the another user', () => { + userPage.getGlobalFeed(); + userPage.goToProfile(); + userPage.unfollowUser(); + userPage.pageHasFollowBtn(); }); }); diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 40634fe9..160ebf0f 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -32,6 +32,10 @@ Cypress.Commands.add('getByDataCy', (selector) => { cy.get(`[data-cy="${selector}"]`); }); +Cypress.Commands.add('getByDataQa', (selector) => { + cy.get(`[data-qa="${selector}"]`); +}); + Cypress.Commands.add('register', (email = 'riot@qa.team', username = 'riot', password = '12345Qwert!') => { cy.request('POST', '/users', { email, @@ -39,3 +43,48 @@ Cypress.Commands.add('register', (email = 'riot@qa.team', username = 'riot', pas password }); }); + +Cypress.Commands.add('login', (email = 'riot@qa.team', username = 'riot', password = '12345Qwert!') => { + cy.request('POST', '/users', { + user: { + email, + username, + password + } + }).then(response => { + const user = { + bio: response.body.user.bio, + effectiveImage: "https://static.productionready.io/images/smiley-cyrus.jpg", + email: response.body.user.email, + image: response.body.user.image, + token: response.body.user.token, + username: response.body.user.username, + }; + window.localStorage.setItem('user', JSON.stringify(user)); + cy.setCookie('auth', response.body.user.token); + }); +}); + +Cypress.Commands.add('createArticle', (title, description, body) => { + cy.getCookie('auth').then((token) => { + const authToken = token.value; + + cy.request({ + method: 'POST', + url: '/api/articles', + body: { + article: { + title, + description, + body, + tagList: [] + } + }, + headers: { + Authorization: `Token ${authToken}` + } + }).then((response) => { + cy.visit('/article/' + response.body.article.slug); + }); + }); +}); diff --git a/cypress/support/index.d.ts b/cypress/support/index.d.ts index 00f9d075..a372e873 100644 --- a/cypress/support/index.d.ts +++ b/cypress/support/index.d.ts @@ -3,6 +3,7 @@ declare namespace Cypress { interface Chainable { getByDataCy(selector: string): Chainable + getByDataQa(selector: string): Chainable register(email: string, username: string, password: string): Chainable } } diff --git a/cypress/support/pages/article.pageObject.js b/cypress/support/pages/article.pageObject.js new file mode 100644 index 00000000..6fd989f6 --- /dev/null +++ b/cypress/support/pages/article.pageObject.js @@ -0,0 +1,47 @@ +import PageObject from '../PageObject'; + +class ArticlePageObject extends PageObject { + url = '/editor'; + + get articleTitle() { + return cy.getByDataQa('article_title'); + } + + typeArticleTitle(title) { + this.articleTitle.clear().type(title); + } + + get articleDesc() { + return cy.getByDataQa('article_desc'); + } + + typeArticleDesc(desc) { + this.articleDesc.clear().type(desc); + } + + get articleBody() { + return cy.getByDataQa('article_body'); + } + + typeArticleBody(body) { + this.articleBody.clear().type(body); + } + + publishArticle() { + cy.getByDataQa('publish_btn').click(); + } + + editArticle() { + cy.getByDataQa('edit_btn').click(); + } + + deleteArticle() { + cy.getByDataQa('delete_btn').click(); + } + + updateArticle() { + cy.contains('button.btn', 'Update').click(); + } +} + +export default ArticlePageObject; diff --git a/cypress/support/pages/settings.pageObject.js b/cypress/support/pages/settings.pageObject.js new file mode 100644 index 00000000..df25bb39 --- /dev/null +++ b/cypress/support/pages/settings.pageObject.js @@ -0,0 +1,47 @@ +import PageObject from '../PageObject'; + +class SettingsPageObject extends PageObject { + url = '/settings'; + + get usernameField() { + return cy.getByDataQa('username-set'); + } + + typeUsernameField(username) { + this.usernameField.clear().type(username); + } + + get bioField() { + return cy.getByDataQa('bio-set'); + } + + typeBioField(bio) { + this.bioField.clear().type(bio); + } + + get emailField() { + return cy.getByDataQa('email-set'); + } + + typeEmailField(email) { + this.emailField.clear().type(email); + } + + get passField() { + return cy.getByDataQa('pass-set'); + } + + typePassField(pass) { + this.passField.clear().type(pass); + } + + updateSettings() { + cy.getByDataQa('updateBtn-set').click(); + } + + logoutFromSettings() { + cy.getByDataQa('logoutBtn-set').click(); + } +} + +export default SettingsPageObject; diff --git a/cypress/support/pages/signIn.pageObject.js b/cypress/support/pages/signIn.pageObject.js index 3a1e21c8..f5059ef7 100644 --- a/cypress/support/pages/signIn.pageObject.js +++ b/cypress/support/pages/signIn.pageObject.js @@ -29,6 +29,11 @@ class SignInPageObject extends PageObject { this.signInBtn .click(); } + + assertErrorMessage(message) { + cy.get('ul.error-messages li') + .should('contain.text', message); + } } export default SignInPageObject; diff --git a/cypress/support/pages/signUp.pageObject.js b/cypress/support/pages/signUp.pageObject.js new file mode 100644 index 00000000..4bd071d6 --- /dev/null +++ b/cypress/support/pages/signUp.pageObject.js @@ -0,0 +1,48 @@ +import PageObject from '../PageObject'; + +class SignUpPageObject extends PageObject { + url = '/user/register'; + + get emailField() { + return cy.getByDataQa('email-sign-up'); + } + + get passwordField() { + return cy.getByDataQa('password-sign-up'); + } + + get usernameField() { + return cy.getByDataQa('username-sign-up'); + } + + get signUpBtn() { + return cy.getByDataQa('btn-sign-up'); + } + + typeEmail(email) { + this.emailField + .type(email); + } + + typePassword(password) { + this.passwordField + .type(password); + } + + typeUsername(username) { + this.usernameField + .type(username); + } + + clickSignUpBtn() { + this.signUpBtn + .click(); + } + + assertErrorMessage(message) { + cy.get('ul.error-messages li:nth-child(2)') + .should('contain.text', message); + } +} + +export default SignUpPageObject; diff --git a/cypress/support/pages/user.pageObject.js b/cypress/support/pages/user.pageObject.js new file mode 100644 index 00000000..9cbeddc7 --- /dev/null +++ b/cypress/support/pages/user.pageObject.js @@ -0,0 +1,32 @@ +/// + +import PageObject from '../PageObject'; + +class UserPageObject extends PageObject { + + getGlobalFeed() { + cy.getByDataQa('global-feed').click(); + } + + goToProfile() { + cy.get('div.article-meta a').click(); + } + + followUser() { + cy.getByDataQa('follow-button').click(); + } + + unfollowUser() { + cy.getByDataQa('unfollow-button').click(); + } + + pageHasUnfollowBtn() { + return cy.getByDataQa('unfollow-button'); + } + + pageHasFollowBtn() { + return cy.getByDataQa('follow-button'); + } +} + +export default UserPageObject; diff --git a/src/vue/components/ArticleActions.vue b/src/vue/components/ArticleActions.vue index 3f201da2..7a0fda53 100644 --- a/src/vue/components/ArticleActions.vue +++ b/src/vue/components/ArticleActions.vue @@ -2,11 +2,11 @@ -  Edit Article +  Edit Article    diff --git a/src/vue/routes/ArticleEdit.vue b/src/vue/routes/ArticleEdit.vue index 31292239..98b5361e 100644 --- a/src/vue/routes/ArticleEdit.vue +++ b/src/vue/routes/ArticleEdit.vue @@ -11,6 +11,7 @@ type="text" class="form-control form-control-lg" v-model="article.title" + data-qa="article_title" placeholder="Article Title" /> @@ -19,6 +20,7 @@ type="text" class="form-control" v-model="article.description" + data-qa="article_desc" placeholder="What's this article about?" /> @@ -27,6 +29,7 @@ class="form-control" rows="8" v-model="article.body" + data-qa="article_body" placeholder="Write your article (in markdown)" > @@ -44,6 +47,7 @@ diff --git a/src/vue/routes/Settings.vue b/src/vue/routes/Settings.vue index d3a70fde..02bb326d 100644 --- a/src/vue/routes/Settings.vue +++ b/src/vue/routes/Settings.vue @@ -19,6 +19,7 @@ class="form-control form-control-lg" type="text" v-model="user.username" + data-qa="username-set" placeholder="Your username" /> @@ -27,6 +28,7 @@ class="form-control form-control-lg" rows="8" v-model="user.bio" + data-qa="bio-set" placeholder="Short bio about you" > @@ -35,6 +37,7 @@ class="form-control form-control-lg" type="text" v-model="user.email" + data-qa="email-set" placeholder="Email" /> @@ -43,17 +46,18 @@ class="form-control form-control-lg" type="password" v-model="user.password" + data-qa="pass-set" placeholder="Password" /> -
-