Skip to content

Commit

Permalink
initial cypress setup and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ivandotv committed Jul 5, 2022
1 parent 3dc0f62 commit 65d695e
Show file tree
Hide file tree
Showing 50 changed files with 1,147 additions and 290 deletions.
91 changes: 91 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Note: You can use any Debian/Ubuntu based image you want.
FROM mcr.microsoft.com/vscode/devcontainers/base:0-bullseye


# [Option] Install zsh
ARG INSTALL_ZSH="true"
# [Option] Upgrade OS packages to their latest versions
Expand All @@ -27,9 +28,99 @@ RUN apt-get update \
# Clean up
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts/



# Cypress dependencies https://github.com/cypress-io/cypress-docker-images/blob/master/base/16.14.2/Dockerfile
RUN apt-get update && \
apt-get install --no-install-recommends -y \
libgtk2.0-0 \
libgtk-3-0 \
libnotify-dev \
libgconf-2-4 \
libgbm-dev \
libnss3 \
libxss1 \
libasound2 \
libxtst6 \
xauth \
xvfb

# Browser dependencies https://github.com/cypress-io/cypress-docker-images/blob/master/browsers/node16.14.2-slim-chrome100-ff99-edge/Dockerfile
RUN apt-get update && \
apt-get install --no-install-recommends -y \
libcurl4 \
libcurl3-gnutls \
libcurl3-nss \
xdg-utils \
wget \
curl \
# firefox dependencies
bzip2 \
# add codecs needed for video playback in firefox
# https://github.com/cypress-io/cypress-docker-images/issues/150
mplayer \
# edge dependencies
gnupg \
dirmngr

# install libappindicator3-1 - not included with Debian 11
RUN wget --no-verbose /usr/src/libappindicator3-1_0.4.92-7_amd64.deb "http://ftp.us.debian.org/debian/pool/main/liba/libappindicator/libappindicator3-1_0.4.92-7_amd64.deb" && \
dpkg -i /usr/src/libappindicator3-1_0.4.92-7_amd64.deb ; \
apt-get install -f -y && \
rm -f /usr/src/libappindicator3-1_0.4.92-7_amd64.deb

# install Chrome browser
RUN wget --no-verbose -O /usr/src/google-chrome-stable_current_amd64.deb "http://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_100.0.4896.88-1_amd64.deb" && \
dpkg -i /usr/src/google-chrome-stable_current_amd64.deb ; \
apt-get install -f -y && \
rm -f /usr/src/google-chrome-stable_current_amd64.deb

# "fake" dbus address to prevent errors
# https://github.com/SeleniumHQ/docker-selenium/issues/87
ENV DBUS_SESSION_BUS_ADDRESS=/dev/null

# install Firefox browser
RUN wget --no-verbose -O /tmp/firefox.tar.bz2 https://download-installer.cdn.mozilla.net/pub/firefox/releases/99.0.1/linux-x86_64/en-US/firefox-99.0.1.tar.bz2 && \
tar -C /opt -xjf /tmp/firefox.tar.bz2 && \
rm /tmp/firefox.tar.bz2 && \
ln -fs /opt/firefox/firefox /usr/bin/firefox

RUN echo "Downloading Latest Edge version..."

## Setup Edge
RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
RUN install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/
RUN sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/edge stable main" > /etc/apt/sources.list.d/microsoft-edge-dev.list'
RUN rm microsoft.gpg

## Install Edge
RUN apt-get update
RUN apt-get install -y microsoft-edge-dev

# Add a link to the browser that allows Cypress to find it
RUN ln -s /usr/bin/microsoft-edge /usr/bin/edge

# versions of local tools
RUN echo " node version: $(node -v) \n" \
"npm version: $(npm -v) \n" \
"yarn version: $(yarn -v) \n" \
"debian version: $(cat /etc/debian_version) \n" \
"Chrome version: $(google-chrome --version) \n" \
"Firefox version: $(firefox --version) \n" \
"Edge version: $(edge --version) \n" \
"git version: $(git --version) \n" \
"whoami: $(whoami) \n"


# cleanup
RUN rm -rf /var/lib/apt/lists/* \
&& apt-get clean


# Setting the ENTRYPOINT to docker-init.sh will configure non-root access
# to the Docker socket. The script will also execute CMD as needed.
ENTRYPOINT [ "/usr/local/share/docker-init.sh" ]

CMD [ "sleep", "infinity" ]

# [Optional] Uncomment this section to install additional OS packages.
Expand Down
3 changes: 3 additions & 0 deletions .devcontainer/setup.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ await $`npm i pnpm@6 --location=global`
// install dependencies
await $`pnpm i`

// install cypress executable
await $`pnpm cypress install`

// automatically sign commits
await $`git config --global commit.gpgsign true`
4 changes: 1 addition & 3 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ module.exports = {
env: {
browser: true,
es6: true,
node: true,
jest: true
node: true
},
globals: {
__DEV__: true,
Expand All @@ -16,7 +15,6 @@ module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:jest/recommended',
'next',
'prettier'
],
Expand Down
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@ yarn-error.log*
# Sentry
.sentryclirc

# Sentry
.sentryclirc
# Cypress
cypress/videos
cypress/screenshots
8 changes: 8 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { defineConfig } from 'cypress'

export default defineConfig({
video: false,
e2e: {
baseUrl: 'http://localhost:3000'
}
})
10 changes: 10 additions & 0 deletions cypress/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
env: {
browser: true,
es6: true,
node: true,
'cypress/globals': true
},
plugins: ['cypress'],
extends: ['../.eslintrc.js', 'plugin:cypress/recommended']
}
23 changes: 23 additions & 0 deletions cypress/cypress.global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/// <reference types="cypress" />
declare global {
namespace Cypress {
interface Chainable {
// login(email: string, password: string): Chainable<void>
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>

getBySel(
dataTestAttribute: string,
args?: any
): Chainable<JQuery<HTMLElement>>
getBySelLike(
dataTestPrefixAttribute: string,
args?: any
): Chainable<JQuery<HTMLElement>>
waitShellVisible(): Chainable<JQuery<HTMLElement>>
}
}
}

export {}
14 changes: 14 additions & 0 deletions cypress/e2e/app-home.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
describe('App home', () => {
beforeEach(() => {
cy.visit('/app')
cy.waitShellVisible()
})

it('shows main navigation buttons', () => {
cy.getBySel('local-radio').should('be.visible')
cy.getBySel('by-genre').should('be.visible')
cy.getBySel('by-location').should('be.visible')
cy.getBySel('by-language').should('be.visible')
cy.getBySel('custom-search').should('be.visible')
})
})
81 changes: 81 additions & 0 deletions cypress/e2e/geolocation/geolocation-error.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
describe('Geolocation error', () => {
beforeEach(() => {
cy.visit('/app')
cy.waitShellVisible()
})

beforeEach(() => {
cy.intercept('api/geolocation', {
statusCode: 303,
body: { error: 'Service unavailable' },
delay: 500
}).as('geolocation')
})

it('shows progress modal', () => {
cy.getBySel('local-radio').click()

cy.getBySel('location-modal').as('modal')

cy.get('@modal')
.should('be.visible')
.should('contain.text', 'Determining your location')

cy.get('[role=progressbar]').as('progressbar')

cy.get('@progressbar').should('be.visible')

cy.wait('@geolocation')

cy.get('@progressbar').should('not.exist')
})

it('shows failed modal', () => {
cy.getBySel('local-radio').click()

cy.getBySel('location-modal').as('modal')

cy.wait('@geolocation')

cy.get('@modal').contains(/Sorry, couldn't get your location/i)

cy.get('@modal').find('button').contains(/close/i).as('close_btn')

cy.get('@modal')
.find('button')
.contains(/choose the location/i)
.as('choose_btn')

cy.get('@close_btn').should('be.visible')
cy.get('@choose_btn').should('be.visible')
})

it('removes failed modal', () => {
cy.getBySel('local-radio').click()

cy.getBySel('location-modal').as('modal')

cy.wait('@geolocation')

cy.get('@modal').find('button').contains(/close/i).as('close_btn')

cy.get('@close_btn').click()

cy.get('@modal').should('not.exist')
})

it('goes to manual location', () => {
cy.getBySel('local-radio').click()

cy.getBySel('location-modal').as('modal')

cy.wait('@geolocation')

cy.get('@modal')
.find('button')
.contains(/choose the location/i)
.click()

cy.location('pathname').should('match', /\/app\/by-location$/)
})
})
96 changes: 96 additions & 0 deletions cypress/e2e/geolocation/geolocation-success.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
const countryCode = {
code: 'RS',
cont: 'EU',
flag: '🇷🇸',
name: 'Serbia'
}
describe('Geolocation success', () => {
beforeEach(() => {
cy.visit('/app')
cy.waitShellVisible()
})

beforeEach(() => {
cy.intercept('api/geolocation', {
statusCode: 200,
body: countryCode,
delay: 500
}).as('geolocation')
})

it('shows progress modal', () => {
cy.getBySel('local-radio').click()

cy.getBySel('location-modal').as('modal')

cy.get('@modal')
.should('be.visible')
.should('contain.text', 'Determining your location')

cy.get('[role=progressbar]').as('progressbar')

cy.get('@progressbar').should('be.visible')

cy.wait('@geolocation')

cy.get('@progressbar').should('not.exist')
})

it('shows success modal', () => {
cy.getBySel('local-radio').click()

cy.getBySel('location-modal').as('modal')

cy.wait('@geolocation')

cy.get('@modal').contains(/Your location is/i)

cy.get('@modal')
.find('button')
.contains(/different location/i)
.should('be.visible')

cy.get('@modal')
.find('button')
.contains(/let's go/i)
.should('be.visible')

cy.get('@modal').contains(countryCode.flag).should('be.visible')
cy.get('@modal').contains(countryCode.name).should('be.visible')
})

it('goes to manual location', () => {
cy.getBySel('local-radio').click()

cy.getBySel('location-modal').as('modal')

cy.wait('@geolocation')

cy.get('@modal')
.find('button')
.contains(/choose different location/i)
.click()

cy.location('pathname').should('match', /\/app\/by-location$/)
})

it('goes to found country ip', () => {
cy.getBySel('local-radio').click()

cy.getBySel('location-modal').as('modal')

cy.wait('@geolocation')

cy.get('@modal')
.find('button')
.contains(/let's go/i)
.click()

// example: https://live-radio.vercel.app/app/by-location/EU/RS
const location = new RegExp(
`/app/by-location/${countryCode.cont}/${countryCode.code}$`
)

cy.location('pathname', { timeout: 20000 }).should('match', location)
})
})
13 changes: 13 additions & 0 deletions cypress/e2e/landing-page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
describe('Landing page', () => {
it('shows login buttons', () => {
cy.visit('/')

cy.getBySel('login').contains(/sign in or register/i)

cy.getBySel('anonymous')
.contains(/anonymous user/i)
.click()

cy.location('pathname').should('match', /\/app$/)
})
})
Loading

1 comment on commit 65d695e

@vercel
Copy link

@vercel vercel bot commented on 65d695e Jul 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

next-radio – ./

live-radio.vercel.app
next-radio-git-master-ivandotv.vercel.app
next-radio-ivandotv.vercel.app

Please sign in to comment.