Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

360-fix-e2e-specs #371

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d924336
wip: fix the broken browse test
DaltonMcauliffe Feb 5, 2024
5dceb17
refactor browse.cy.js
alishaevn Feb 5, 2024
5c01246
Merge branch 'main' into 360-fix-e2e-specs
Feb 6, 2024
d309919
Restored previously working browse specs
Feb 6, 2024
0997e35
fix the broken browse page specs
alishaevn Feb 8, 2024
8d41406
update the browse spec to check 10 services
alishaevn Feb 8, 2024
573bee6
browser spec updated
Feb 8, 2024
5ed092a
able to log in a user on the browse spec
alishaevn Feb 8, 2024
175c037
Merge branch '360-fix-e2e-specs' of https://github.com/scientist-soft…
alishaevn Feb 8, 2024
2e0d5d5
correctly testing that reaching a request page as a logged in user works
alishaevn Feb 8, 2024
326b54d
remove the 'only'
alishaevn Feb 8, 2024
f222cac
small browse refactor for timeout
alishaevn Feb 8, 2024
abcfa62
update instructions around `TEST_SESSION_COOKIE`
alishaevn Feb 8, 2024
a8eef12
Merge branch 'main' into 360-fix-e2e-specs
alishaevn Feb 9, 2024
9d1a8ac
increase the default timeout for browse tests
alishaevn Feb 9, 2024
db10801
cypress env updates
alishaevn Feb 9, 2024
b782b26
forgot to add NEXT_PUBLIC_TOKEN to the cypress workflow secrets
alishaevn Feb 9, 2024
ae53512
specify the environment to use for cypress tests
alishaevn Feb 12, 2024
c988026
add the `NEXTAUTH_URL` to the cypress job
alishaevn Feb 12, 2024
511f7d9
only request 10 services in the browse specs
alishaevn Feb 13, 2024
49989cb
create the waitForElement command
alishaevn Feb 13, 2024
d566d87
formatting
alishaevn Feb 13, 2024
3479ce0
run cypress specs headed in ci
alishaevn Feb 13, 2024
d09233e
pass cypress workflow specific command
alishaevn Feb 13, 2024
bd00f6c
use port 3001 in ci
alishaevn Feb 13, 2024
f5a064d
remove ci related code in favor of #378
alishaevn Feb 13, 2024
064dfa3
add descriptions for newly added cypress commands
alishaevn Feb 13, 2024
7bdd439
rearrange order of browse tests in an attempt to reduce flakiness
alishaevn Feb 13, 2024
a6de9cd
increase the defaultCommandTimeout
alishaevn Feb 14, 2024
9ee6f90
Merge branch 'main' into 360-fix-e2e-specs
alishaevn Feb 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ NEXT_PUBLIC_PROVIDER_ID=0001
NEXT_PUBLIC_PROVIDER_NAME=webstore
NEXT_PUBLIC_SCIENTIST_API_VERSION=v2
NEXT_PUBLIC_WEBHOOK_URL=http://ss-mailer/webstore
TEST_SESSION_COOKIE= #ref: https://github.com/scientist-softserv/webstore?tab=readme-ov-file#cypress-env-variables
5 changes: 5 additions & 0 deletions .github/workflows/build-test-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ jobs:
with:
start: yarn start
wait-on: 'http://localhost:3000'
env:
NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET }}
NEXTAUTH_URL: ${{ secrets.NEXTAUTH_URL }}
NEXT_PUBLIC_TOKEN: ${{ secrets.NEXT_PUBLIC_TOKEN }}
TEST_SESSION_COOKIE: ${{ secrets.TEST_SESSION_COOKIE }}
eslint:
needs: build
uses: scientist-softserv/actions/.github/workflows/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ There are 2 types of Cypress tests, e2e & component.
If you are creating an e2e test, it will live in the `cypress/e2e` directory. Component tests will need to be created in a directory called `cypress/component `

#### Cypress ENV Variables
- the Cypress suite requires an environment variable that should be stored in your `.env` and not committed to git.
- the Cypress suite requires an environment variable that should be stored in your `.env`.
- TEST_SESSION_COOKIE=
- to get the value for this variable, open your browser to your running app at `localhost:3000`
- sign in
Expand Down
1 change: 1 addition & 0 deletions cypress.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ module.exports = defineConfig({
},
},
env: {
API_PER_PAGE: 10,
CYPRESS_SEARCH_QUERY: 'test',
NEXT_PUBLIC_PROVIDER_ID: process.env.NEXT_PUBLIC_PROVIDER_ID,
NEXT_PUBLIC_PROVIDER_NAME: process.env.NEXT_PUBLIC_PROVIDER_NAME,
Expand Down
140 changes: 58 additions & 82 deletions cypress/e2e/browse.cy.js
Original file line number Diff line number Diff line change
@@ -1,105 +1,81 @@
describe('Browsing', () => {
let wares
let loading
let error
let intercepts = [
{
alias: 'useFilteredWares',
},
{
alias: 'useFilteredWares - blank search',
},
{
alias: 'useFilteredWares - with results',
query: 'test',
},
{
alias: 'useFilteredWares - no results',
query: 'asdfghjk',
emptyFixture: 'services/no-wares.json',
},
]
/**
* In order to ensure that any changes against the API do not negatively
* affect the critical path of browsing all services and creating a request,
* we will not stub the API calls for the browse page.
*/

describe('Navigating to the browse page', () => {
beforeEach(() => {
// Intercept the responses from the endpoint to view all requests.
// Even though this is to the same endpoint, the call happens on each page twice,
// once when the page loads with all the wares, and again after any search is performed.
// this makes it necessary to create an intercept for each time the call is made.
intercepts.forEach((intercept) => {
cy.customApiIntercept({
action: 'GET',
alias: intercept.alias,
requestURL: `/providers/${Cypress.env('NEXT_PUBLIC_PROVIDER_ID')}/wares.json?q=${intercept.query || ''}`,
data: wares,
defaultFixture: 'services/wares.json',
emptyFixture: intercept.emptyFixture || '',
loading,
error
cy.useFilteredWares()
cy.visit('/browse')
})

context('while content is loading', () => {
it('should show loading components.', () => {
cy.get(".card-body[data-cy='item-loading']").should('be.visible').then(() => {
cy.log('Loading components display correctly.')
})
})
})

describe('from the browse page', () => {
beforeEach(() => {
cy.visit('/browse')
context('and conducting a search', () => {
it('with no query, returns all services', () => {
cy.get('button.search-button').click()
cy.url().should('include', '/browse')
cy.url().should('not.include', '?')
cy.get('input.search-bar').should('have.value', '')
cy.get(".card[data-cy='item-card']").should('be.visible')
})

context('browse page is loading', () => {
before(() => {
loading = true
})
it('should show loading components.', () => {
cy.get(".card-body[data-cy='item-loading']").should('be.visible').then(() => {
cy.log('Loading components display correctly.')
})
})
it('with a valid query, returns matching services', () => {
cy.get('input.search-bar').type(Cypress.env('CYPRESS_SEARCH_QUERY'))
cy.get('button.search-button').click()
cy.url().should('include', `/browse?q=${Cypress.env('CYPRESS_SEARCH_QUERY')}`)
cy.get('input.search-bar').should('have.value', Cypress.env('CYPRESS_SEARCH_QUERY'))
cy.get(".card[data-cy='item-card']").should('be.visible')
})

context('error while making a request to the api', () => {
before(() => {
loading = false
error = true
it('with an invalid query, returns no services', () => {
cy.get('input.search-bar').type('asdfghjk')
cy.get('button.search-button').click()
cy.url().should('include', '/browse?q=asdfghjk')
cy.get('input.search-bar').should('have.value', 'asdfghjk')
cy.get("p[data-cy='no-results']").should('contain', 'Your search for asdfghjk returned no results')
})
})

context('and creating a new request', () => {
beforeEach(() => {
cy.waitForElement('[data-cy="linked-button"]')
cy.get('[data-cy="linked-button"]').then(($buttons) => {
const randomIndex = Math.floor(Math.random() * Cypress.env('API_PER_PAGE'))
cy.wrap($buttons.eq(randomIndex)).click()
})
it('should show an error message.', () => {
})

context('as a logged out user', () => {
it('shows a disabled request form, with an error message.', () => {
cy.get("div[role='alert']").should('be.visible').then(() => {
cy.log('Successfully hits an error.')
})
cy.get('div.alert-heading').should('have.text', 'Sign in required')
cy.get('form.rjsf').should('be.visible')
cy.scrollTo('bottom')
cy.get('button.btn-primary').should('be.disabled')
})
})

// filtering by query is handled in the api and not the webstore
// since we are stubbing that response, our tests will not return actual filtered wares based on on test query.
// the purpose of these tests is just to show that the correct components appear in the UI in each case.
context('a search is completed successfully and', () => {
context('as a logged in user', () => {
before(() => {
wares = true
error = false
})
it('has a blank query', () => {
cy.get('button.search-button').click()
cy.url().should('include', '/browse')
cy.url().should('not.include', '?')
cy.get('input.search-bar').should('have.value', '')
cy.get(".card[data-cy='item-card']").should('be.visible')
cy.login(Cypress.env('TEST_SCIENTIST_USER'), Cypress.env('TEST_SCIENTIST_PW'))
})

it('has a query term', () => {
cy.get('input.search-bar').type('test')
cy.get('button.search-button').click()
cy.url().should('include', '/browse?q=test')
cy.get('input.search-bar').should('have.value', 'test')
cy.get(".card[data-cy='item-card']").should('be.visible')
})

before(() => {
wares = false
})
it('has a query term, but that term has no results', () => {
cy.get('input.search-bar').type('asdfghjk')
cy.get('button.search-button').click()
cy.url().should('include', '/browse?q=asdfghjk')
cy.get('input.search-bar').should('have.value', 'asdfghjk')
cy.get("p[data-cy='no-results']").should('contain', 'Your search for asdfghjk returned no results')
it('shows a valid request form.', () => {
cy.waitForElement('form.rjsf')
cy.get("div[role='alert']").should('not.exist')
cy.get('form.rjsf').should('be.visible')
cy.scrollTo('bottom')
cy.get('button.btn-primary').should('be.enabled')
})
})
})
Expand Down
2 changes: 1 addition & 1 deletion cypress/fixtures/session.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
},
"expires": "3000-01-01T00:00:00.000Z",
"accessToken": "abcdefghijklmnopqrst"
}
}
19 changes: 19 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,22 @@ Cypress.Commands.add('customApiIntercept', ({
return req.reply(response.data || response.error || {})
}).as(alias || 'customIntercept')
})

/**
* Intercept the useFilteredWares API call to modify the per_page query
* parameter. We're lowering it in an attempt to speed up the test. Then,
* we continue to hit the server with the modified request.
*/
Cypress.Commands.add('useFilteredWares', () => {
cy.intercept(/\/wares\.json\?per_page=2000&q.*/, (req) => {
req.url = req.url.replace(/per_page=\d+/, `per_page=${Cypress.env('API_PER_PAGE')}`)
req.continue()
})
})

/**
* To avoid the flakiness of the test, we wait for the element to exist
*/
Cypress.Commands.add('waitForElement', (selector) => {
cy.get(selector).should('exist')
})
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "webstore",
"version": "0.1.8",
"private": true,
"homepage": "https://github.com/scientist-softserv/webstore#readme",
"engines": {
"node": "^18.13.0"
},
Expand Down
Loading