Skip to content

Commit

Permalink
Add user details tests (TonyMckes#3)
Browse files Browse the repository at this point in the history
* Add user details tests

* Execute Cypress workflow on pull request
  • Loading branch information
hugoguillin authored Mar 23, 2024
1 parent b6369b6 commit 64d9b7c
Showing 9 changed files with 197 additions and 81 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
name: Run Cypress tests

on:
pull_request:
branches:
- main
workflow_dispatch:
inputs:
TAGS:
63 changes: 32 additions & 31 deletions cypress/api-utils/article-api.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,67 @@
const url = Cypress.env('apiUrl')
const url = Cypress.env("apiUrl");

export default class Articles {
static getArticles() {
return cy.request(url + '/articles?limit=10').then(response => {
expect(response.status).to.eq(200)
return response.body.articles
})
static getArticles(limit = 10) {
return cy.request(url + "/articles?limit=" + limit).then((response) => {
expect(response.status).to.eq(200);
return response.body.articles;
});
}

static getArticlesByAuthor(authorName) {
return cy
.request({
url: url + `/articles?author=${authorName}&limit=10`,
headers: {
Authorization: 'Token ' + Cypress.env('token')
}
})
.then(response => {
expect(response.status).to.eq(200)
return response.body.articles
Authorization: "Token " + Cypress.env("token"),
},
})
.then((response) => {
expect(response.status).to.eq(200);
return response.body.articles;
});
}

static getArticlesByTag(tagName) {
return cy
.request({
url: url + `/articles?tag=${tagName}&limit=10`,
headers: {
Authorization: 'Token ' + Cypress.env('token')
}
})
.then(response => {
expect(response.status).to.eq(200)
return response.body.articles
Authorization: "Token " + Cypress.env("token"),
},
})
.then((response) => {
expect(response.status).to.eq(200);
return response.body.articles;
});
}

static deleteAuthorArticles(authorName) {
Articles.getArticlesByAuthor(authorName).then(articles => {
Articles.getArticlesByAuthor(authorName).then((articles) => {
articles.forEach((article) => {
cy.request({
method: 'DELETE',
method: "DELETE",
url: `${url}/articles/${article.slug}`,
headers: {
Authorization: 'Token ' + Cypress.env('token')
}
})
})
})
Authorization: "Token " + Cypress.env("token"),
},
});
});
});
}

static createNewArticle(article) {
return cy
.request({
method: 'POST',
method: "POST",
url: `${url}/articles`,
body: article,
headers: {
Authorization: 'Token ' + Cypress.env('token')
}
})
.then(response => {
return response.body.article.slug
Authorization: "Token " + Cypress.env("token"),
},
})
.then((response) => {
return response.body.article.slug;
});
}
}
56 changes: 32 additions & 24 deletions cypress/api-utils/favorites-api.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import ArticlesApi from '../api-utils/article-api'
const url = Cypress.env('apiUrl')
import ArticlesApi from "../api-utils/article-api";
const url = Cypress.env("apiUrl");

export default class FavoritesApi {
static getUserFavorites(username) {
return cy
.request(`${url}/articles?favorited=${username}`)
.then(response => {
return response.body.articles
})
.request(`${url}/articles?favorited=${username}&&limit=10`)
.then((response) => {
return response.body.articles;
});
}

/**
@@ -16,33 +16,41 @@ export default class FavoritesApi {
* @param index Index of the article selected for the test
*/
static unfavoriteArticle(index = 0) {
let slug = ''
let finalSlug
let slug = "";
let finalSlug;
ArticlesApi.getArticles()
.then(articles => {
slug = articles[index].slug
.then((articles) => {
slug = articles[index].slug;
})
.then(() => {
// cy.fixture('loginData').then(loginData => {
this.getUserFavorites(Cypress.env("username")).then(article => {
article.forEach(a => {
if (a.slug === slug) {
finalSlug = slug
}
})
})
// })
this.getUserFavorites(Cypress.env("username")).then((article) => {
article.forEach((a) => {
if (a.slug === slug) {
finalSlug = slug;
}
});
});
})
.then(() => {
if (finalSlug !== undefined) {
cy.request({
method: 'DELETE',
method: "DELETE",
url: `${url}/articles/${slug}/favorite`,
headers: {
Authorization: 'Token ' + Cypress.env('token')
}
})
Authorization: "Token " + Cypress.env("token"),
},
});
}
})
});
}

static favoriteArticle(slug) {
cy.request({
method: "POST",
url: `${url}/articles/${slug}/favorite`,
headers: {
Authorization: "Token " + Cypress.env("token"),
},
});
}
}
2 changes: 1 addition & 1 deletion cypress/e2e/author-detail-test.cy.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import AuthorDetailPage from "../page-objects/author-detail-page.cy";
import AuthorDetailPage from "../page-objects/author-detail-page";
import ArticlesApi from "../api-utils/article-api";
import FollowAuthorButton from "../components/follow-author-button";

87 changes: 87 additions & 0 deletions cypress/e2e/user-details-test.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import Utils from "../utils/utils";
import ArticlesApi from "../api-utils/article-api";
import FavoritesApi from "../api-utils/favorites-api";
import UserDetailsPage from "../page-objects/user-details-page";
import GlobalFeedPage from "../page-objects/global-feed-page";

describe("Check user detail page", { tags: "@user" }, () => {
before(() => {
cy.setJwtTokenAsEnv(Cypress.env("email"), Cypress.env("password"));
});
beforeEach(() => {
cy.loginWithSession(Cypress.env("email"), Cypress.env("password"));
UserDetailsPage.visit();
});

it("Check settings button has correct link", () => {
UserDetailsPage.goToSettingsButton().should(
"have.attr",
"href",
"#/settings"
);
});

context("Check user articles", () => {
before(() => {
// Let's make sure user has at least 5 articles
for (let i = 0; i < 5; i++) {
let newArticle = Utils.generateNewArticleData();
ArticlesApi.createNewArticle(newArticle);
}
});
it("Expected user articles are displayed", () => {
UserDetailsPage.myArticles().should("have.class", "active");
ArticlesApi.getArticlesByAuthor(Cypress.env("username")).as(
"articlesBack"
);
GlobalFeedPage.getArticlesTitles().then((titles) => {
cy.get("@articlesBack").then((articles) => {
expect(titles).to.deep.members(
articles.map((article) => article.title)
);
});
});
});
});

context("Check user favorited articles", () => {
before(() => {
// In order for the test to be deterministic, first we need to unfavorite all articles
FavoritesApi.getUserFavorites(Cypress.env("username")).then(
(articles) => {
articles.forEach((article) => {
cy.request({
method: "DELETE",
url: `${Cypress.env("apiUrl")}/articles/${article.slug}/favorite`,
headers: {
Authorization: "Token " + Cypress.env("token"),
},
});
});
}
);

// Then, let's favorite 5 articles
ArticlesApi.getArticles().then((articles) => {
const randomArticles = Cypress._.sampleSize(articles, 5);
randomArticles.forEach((article) => {
FavoritesApi.favoriteArticle(article.slug);
});
});
});

it("Expected user favorited articles are displayed", () => {
UserDetailsPage.favoritedArticles().click();
FavoritesApi.getUserFavorites(Cypress.env("username")).as(
"favoritesBack"
);
GlobalFeedPage.getArticlesTitles().then((titles) => {
cy.get("@favoritesBack").then((articles) => {
expect(titles).to.deep.members(
articles.map((article) => article.title)
);
});
});
});
});
});
Binary file added cypress/e2eTest.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed cypress/e2eTests.png
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import ArticlesApi from '../api-utils/article-api'

const ARTICLE_TITLE = 'article-title'

export default class AuthorDetailPage {
static visit() {
ArticlesApi.getArticles().then(response => {
const authorName = response[0].author.username
const encodedAuthorName = encodeURIComponent(authorName)
cy.visit('profile/' + encodedAuthorName)
})
}
static getArticlesTitles() {
return cy.getByTestId(ARTICLE_TITLE).then(article => {
return article
.map((_index, title) => {
return title.textContent
})
.get() //This get transforms the JQuery object's array returned by map method into an array of strings
})
}
static showFavoritedPosts() {
cy.contains('Favorited Articles').click()
}
}
import ArticlesApi from '../api-utils/article-api'

const ARTICLE_TITLE = 'article-title'

export default class AuthorDetailPage {
static visit() {
ArticlesApi.getArticles().then(response => {
const authorName = response[0].author.username
const encodedAuthorName = encodeURIComponent(authorName)
cy.visit('profile/' + encodedAuthorName)
})
}
static getArticlesTitles() {
return cy.getByTestId(ARTICLE_TITLE).then(article => {
return article
.map((_index, title) => {
return title.textContent
})
.get() //This get transforms the JQuery object's array returned by map method into an array of strings
})
}
static showFavoritedPosts() {
cy.contains('Favorited Articles').click()
}
}
17 changes: 17 additions & 0 deletions cypress/page-objects/user-details-page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export default class UserSettingsPage {
static visit() {
cy.visit(`/profile/${Cypress.env("username")}`);
}

static goToSettingsButton() {
return cy.getByTestId("edit-profile-settings");
}

static myArticles() {
return cy.contains("My Articles");
}

static favoritedArticles() {
return cy.contains("Favorited Articles");
}
}

0 comments on commit 64d9b7c

Please sign in to comment.