Skip to content

Commit

Permalink
UI tests for Gatsbygram (#4790)
Browse files Browse the repository at this point in the history
* add cypress as a dev dependency

Signed-off-by: Sriram Thiagarajan <sri.sjc@gmail.com>

* 🎉 initial cypress tests for site title & some data

Signed-off-by: Sriram Thiagarajan <sri.sjc@gmail.com>

* more tests for home page

Signed-off-by: Sriram Thiagarajan <sri.sjc@gmail.com>

* tests for about page

Signed-off-by: Sriram Thiagarajan <sri.sjc@gmail.com>

* more tests for home page

Signed-off-by: Sriram Thiagarajan <sri.sjc@gmail.com>

* remove dummy files created by cypress

Signed-off-by: Sriram Thiagarajan <sri.sjc@gmail.com>

* update all gatsby dependencies to latest tag

Signed-off-by: Sriram Thiagarajan <sri.sjc@gmail.com>

* Run cypress tests on CI

* update all gatsby dependencies to latest tag

* run cypress tests on travis, hopefully

* well, try again to run ui tests on travis

* add cypress videos to gitignore

* uncomment original travis stages

* update cypress project id

Signed-off-by: Sriram Thiagarajan <sri.sjc@gmail.com>

* remove cypress record temporarily

Signed-off-by: Sriram Thiagarajan <sri.sjc@gmail.com>
  • Loading branch information
tsriram authored and KyleAMathews committed Apr 14, 2018
1 parent 036b3c8 commit bed4184
Show file tree
Hide file tree
Showing 14 changed files with 242 additions and 16 deletions.
17 changes: 17 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,23 @@ jobs:
- yarn test
- yarn danger ci

- stage: gatsbygram ui tests
language: node_js
node_js:
- '6'
- '8'
cache:
yarn: true
before_install:
- curl -o- -L https://yarnpkg.com/install.sh | bash
- export PATH=$HOME/.yarn/bin:$PATH
- cd examples/gatsbygram
install:
- yarn
script:
- yarn test


- stage: www graphql docker image build and push
if: (NOT type = pull_request) AND branch = master
env:
Expand Down
1 change: 1 addition & 0 deletions examples/gatsbygram/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
public
.cache
node_modules
cypress/videos/
5 changes: 5 additions & 0 deletions examples/gatsbygram/cypress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"baseUrl": "http://localhost:8000",
"fixturesFolder": "data",
"projectId": "c9d3r3"
}
28 changes: 28 additions & 0 deletions examples/gatsbygram/cypress/integration/about_page_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
describe(`About Page`, () => {
it(`successfully loads`, () => {
cy.visit(`/about`)
})

it(`contains the title with an SVG icon and text "Gatsbygram"`, () => {
cy.getTestElement(`site-title`).get(`svg`)
cy.getTestElement(`site-title`).contains(`Gatsbygram`)
})

it(`clicking on site title takes to home page`, () => {
cy.getTestElement(`site-title`).click()
cy.url().should(`eq`, `${Cypress.config(`baseUrl`)}/`)

// go back to about page for further testing
cy.visit(`/about`)
})

it(`contains a link to about page in nav bar and it works`, () => {
cy.getTestElement(`about-link`).contains(`About`)
cy.getTestElement(`about-link`).click()
cy.url().should(`eq`, `${Cypress.config(`baseUrl`)}/about/`)
})

it(`displays title of the page`, () => {
cy.getTestElement(`about-title`).contains(`About Gatsbygram`)
})
})
106 changes: 106 additions & 0 deletions examples/gatsbygram/cypress/integration/home_page_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@

describe(`The Home Page`, () => {
it(`successfully loads`, () => {
cy.visit(`/`)
})

it(`contains the title with an SVG icon and text "Gatsbygram"`, () => {
cy.getTestElement(`site-title`).get(`svg`)
cy.getTestElement(`site-title`).contains(`Gatsbygram`)
})

it(`contains a link to about page in nav bar and it works`, () => {
cy.getTestElement(`about-link`).contains(`About`)
cy.getTestElement(`about-link`).click()
cy.url().should(`eq`, `${Cypress.config(`baseUrl`)}/about/`)
// go back to home page
cy.visit(`/`)
})

it(`renders user avatar and name`, () => {
cy.getTestElement(`user-avatar`).get(`img`)
cy.getTestElement(`username`).contains(`kyle__mathews`)
})

it(`shows user's posts and followers count`, () => {
cy.getTestElement(`user-meta`).contains(`100 posts`)
cy.getTestElement(`user-meta`).contains(`192k followers`)
})

it(`shows number of likes when hovered on a post`, () => {
cy.fixture(`posts`).then((postsData) => {
const post = postsData[0]
cy.getTestElement(`post`).first().trigger(`mouseover`)
cy.getTestElement(`likes`).contains(post.likes)
cy.getTestElement(`post`).first().trigger(`mouseout`)
})
})

it(`opens and closes a post`, () => {
cy.fixture(`posts`).then((postsData) => {
const post = postsData[0]
cy.getTestElement(`post`).first().click()
cy.url().should('contain', post.id)
cy.getTestElement(`post-detail-avatar`).should(`have.attr`, `src`, post.avatar)
cy.getTestElement(`post-detail-username`).contains(post.username)
cy.getTestElement(`post-detail-likes`).contains(post.likes)
cy.getTestElement(`post-detail-text`).contains(post.username)
cy.getTestElement(`post-detail-text`).contains(post.text)
cy.getTestElement(`modal-close`).click()
cy.url().should(`eq`, `${Cypress.config(`baseUrl`)}/`)
})
})

it(`goes to next / previous post on clicking arrow icons`, () => {
cy.fixture(`posts`).then((postsData) => {
const post1 = postsData[0]
const post2 = postsData[1]
// open fist post
cy.getTestElement(`post`).first().click()
cy.url().should('contain', post1.id)
// click right arrow icon to go to 2nd post
cy.getTestElement(`next-post`).click()
cy.url().should('contain', post2.id)
// press left arrow to go back to 1st post
cy.getTestElement(`previous-post`).click()
cy.url().should('contain', post1.id)
// close the post
cy.getTestElement(`modal-close`).click()
})
})

it(`goes to next / previous post with keyboard shortcut`, () => {
cy.fixture(`posts`).then((postsData) => {
const post1 = postsData[0]
const post2 = postsData[1]
// open fist post
cy.getTestElement(`post`).first().click()
cy.url().should('contain', post1.id)
// press right arrow to go to 2nd post
cy.get(`body`).type(`{rightarrow}`)
cy.url().should('contain', post2.id)
// press left arrow to go back to 1st post
cy.get(`body`).type(`{leftarrow}`)
cy.url().should('contain', post1.id)
// close the post
cy.getTestElement(`modal-close`).click()
})
})

it(`loads more posts when Load More button is clicked & on scroll`, () => {
// initially loads 12 posts
cy.getTestElement(`post`).should('have.length', 12)

// loads 12 more posts when Load More button is clicked
cy.getTestElement(`load-more`).click()
cy.getTestElement(`post`).should('have.length', 24)

// loads 12 more posts when scrolled to bottom
// cy.getTestElement(`home-container`).scrollTo(`0%`, `99%`)
cy.window().scrollTo(`bottom`)
cy.getTestElement(`post`).should('have.length', 36)

// let's go back to top
cy.window().scrollTo(`top`)
})
})
30 changes: 30 additions & 0 deletions examples/gatsbygram/cypress/support/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })

// copied from here - https://github.com/cypress-io/cypress/issues/1212#issuecomment-360395261
Cypress.Commands.add("getTestElement", (selector) => {
return cy.get(`[data-testid="${selector}"]`)
})
20 changes: 20 additions & 0 deletions examples/gatsbygram/cypress/support/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands'

// Alternatively you can use CommonJS syntax:
// require('./commands')
32 changes: 19 additions & 13 deletions examples/gatsbygram/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
"version": "1.0.0",
"author": "Kyle Mathews <mathews.kyle@gmail.com>",
"dependencies": {
"gatsby": "^1.9.52",
"gatsby-image": "^1.0.39",
"gatsby-link": "^1.6.20",
"gatsby-plugin-glamor": "^1.6.8",
"gatsby-plugin-google-analytics": "^1.0.8",
"gatsby-plugin-manifest": "^1.0.8",
"gatsby-plugin-offline": "^1.0.9",
"gatsby-plugin-sharp": "^1.6.8",
"gatsby-source-filesystem": "^1.5.2",
"gatsby-transformer-json": "^1.0.8",
"gatsby-transformer-sharp": "^1.6.8",
"gatsby": "latest",
"gatsby-image": "latest",
"gatsby-link": "latest",
"gatsby-plugin-glamor": "latest",
"gatsby-plugin-google-analytics": "latest",
"gatsby-plugin-manifest": "latest",
"gatsby-plugin-offline": "latest",
"gatsby-plugin-sharp": "latest",
"gatsby-source-filesystem": "latest",
"gatsby-transformer-json": "latest",
"gatsby-transformer-sharp": "latest",
"instagram-screen-scrape": "^2.0.0",
"lodash": "^4.16.4",
"mkdirp": "^0.5.1",
Expand All @@ -38,10 +38,16 @@
"main": "n/a",
"scripts": {
"lint": "./node_modules/.bin/eslint --ext .js,.jsx --ignore-pattern public .",
"test": "echo \"Error: no test specified\" && exit 1",
"test": "start-server-and-test develop http://localhost:8000 cy:run",
"develop": "gatsby develop",
"dev": "gatsby develop",
"build": "gatsby build",
"deploy": "gatsby build --prefix-paths && gh-pages -d public"
"deploy": "gatsby build --prefix-paths && gh-pages -d public",
"cy:open": "cypress open",
"cy:run": "cypress run"
},
"devDependencies": {
"cypress": "^2.1.0",
"start-server-and-test": "^1.1.4"
}
}
3 changes: 3 additions & 0 deletions examples/gatsbygram/src/components/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ class GatsbyGramModal extends React.Component {
}}
>
<CaretLeft
data-testid="previous-post"
css={{
cursor: `pointer`,
fontSize: `50px`,
Expand All @@ -135,6 +136,7 @@ class GatsbyGramModal extends React.Component {
location: { pathname: this.props.location.pathname },
})}
<CaretRight
data-testid="next-post"
css={{
cursor: `pointer`,
fontSize: `50px`,
Expand All @@ -145,6 +147,7 @@ class GatsbyGramModal extends React.Component {
/>
</div>
<Close
data-testid="modal-close"
onClick={() => navigateTo(`/`)}
css={{
cursor: `pointer`,
Expand Down
5 changes: 4 additions & 1 deletion examples/gatsbygram/src/components/post-detail.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class PostDetail extends React.Component {
}}
>
<img
data-testid="post-detail-avatar"
src={avatar}
alt={username}
css={{
Expand All @@ -42,6 +43,7 @@ class PostDetail extends React.Component {
}}
/>
<h5
data-testid="post-detail-username"
css={{
lineHeight: rhythm(1),
marginBottom: rhythm(3 / 4),
Expand All @@ -66,6 +68,7 @@ class PostDetail extends React.Component {
}}
>
<strong
data-testid="post-detail-likes"
css={{
float: `left`,
}}
Expand All @@ -81,7 +84,7 @@ class PostDetail extends React.Component {
{weeksAgo}w
</strong>
</div>
<div>
<div data-testid="post-detail-text">
<strong>{username}</strong> {text}
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions examples/gatsbygram/src/components/post.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class Post extends React.Component {
const { small } = smallImage.childImageSharp
return (
<Link
data-testid="post"
to={`/${id}/`}
onTouchStart={() => (touched = true)}
onMouseEnter={() => {
Expand Down Expand Up @@ -93,6 +94,7 @@ class Post extends React.Component {
{/* overlay */}
{this.state.hovering && (
<div
data-testid="likes"
css={{
position: `absolute`,
top: 0,
Expand Down
2 changes: 2 additions & 0 deletions examples/gatsbygram/src/layouts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class DefaultLayout extends React.Component {
}}
>
<h1
data-testid="site-title"
css={{
...scale(4 / 5),
lineHeight: 1,
Expand Down Expand Up @@ -131,6 +132,7 @@ class DefaultLayout extends React.Component {
</h1>
</Link>
<Link
data-testid="about-link"
to="/about/"
css={{
color: `inherit`,
Expand Down
2 changes: 1 addition & 1 deletion examples/gatsbygram/src/pages/about.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class About extends React.Component {
padding: rhythm(3 / 4),
}}
>
<h1>About Gatsbygram</h1>
<h1 data-testid="about-title">About Gatsbygram</h1>
<p>
Gatsbygram is an example website built with the JavaScript web
framework
Expand Down
Loading

0 comments on commit bed4184

Please sign in to comment.