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

ci: add UI tests for improved release stability #2030

Open
wants to merge 7 commits into
base: alpha
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
23 changes: 23 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,26 @@ jobs:
run: ./scripts/before_script.sh
env:
CI: true
check-e2e:
name: E2E Tests Check
timeout-minutes: 15
runs-on: ubuntu-18.04
steps:
- name: Checkout repo
uses: actions/checkout@v2
- name: Setup and start MongoDB and Parse Server
run: docker-compose up -d
working-directory: cypress
- name: Test dashboard
uses: cypress-io/github-action@v2
with:
start: npm run start
wait-on: 'http://localhost:4040'
wait-on-timeout: 120
browser: chrome
- name: Store video artifacts
if: always()
uses: actions/upload-artifact@v2
with:
name: cypress-videos
path: cypress/videos
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ test_logs

# visual studio code
.vscode

cypress/videos
cypress/screenshots
9 changes: 8 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@ When working on the dashboard, use `npm run dashboard` and visit `localhost:4040

When working on React components, use `npm run pig` and visit `localhost:4041` to view our component library and documentation (you can have both Dashboard and PIG running at once). The demos for each component are the primary way we test components, although there are also a small number of automated tests you can run with `npm test`. If you would like to create a new component that does not exist in the component library, use `npm run generate yourComponentName` to generate boilerplate code and quickly get started.

## Running the e2e tests
We actively welcome your pull requests, please make sure your change is tested and does not break existing tests.

1. Make sure you have Docker and Docker Compose installed and configured.
2. Start testing environment with `docker-compose -f cypress/docker-compose.yml up -d`.
3. Start the dashboard with `npm run dashboard`.
4. Start Cypress Test Runner with `npm run cypress:open` or run tests once with `npm run cypress:run`.

## Pull Requests
We actively welcome your pull requests.

1. Fork the repo and create your branch from the `alpha` branch.
2. If you've added code that should be tested, add tests.
Expand Down
3 changes: 3 additions & 0 deletions cypress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"baseUrl": "http://localhost:4040"
}
8 changes: 8 additions & 0 deletions cypress/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"plugins": [
"cypress"
],
"env": {
"cypress": true
}
}
21 changes: 21 additions & 0 deletions cypress/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
version: "3.9"
services:
mongo:
image: mongo:5.0
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: 123

server:
depends_on:
- mongo
image: parseplatform/parse-server:4.10.4
environment:
PARSE_SERVER_APPLICATION_ID: hello
PARSE_SERVER_MASTER_KEY: world
PARSE_SERVER_DATABASE_URI: mongodb://root:123@mongo:27017/parse?authSource=admin
ports:
- 1337:1337
volumes:
- .:/parse-server/config
- .:/parse-server/cloud
144 changes: 144 additions & 0 deletions cypress/integration/apps-index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/// <reference types="cypress" />

import { getDashboardConfig } from '../utils/getDashboardConfig';

describe('Apps index', () => {
it('Redirects to app lists from root path if there are 2 or more apps', () => {
cy.intercept(
{
method: 'GET',
url: '/parse-dashboard-config.json',
},
getDashboardConfig([
{
appName: 'test1',
},
{
appName: 'test2',
},
]),
);

cy.visit('/');

cy
.url()
.should('match', /\/apps$/);
});

it('Can filter apps with search input', () => {
cy.intercept(
{
method: 'GET',
url: '/parse-dashboard-config.json',
},
getDashboardConfig([
{
appName: 'test1',
},
{
appName: 'test2',
},
]),
);

cy.visit('/apps')

cy
.get('[data-cy="apps-index-app"]')
.should('have.length', 2)

cy
.get('[data-cy="apps-index-search-input"]')
.type('test1')

cy
.get('[data-cy="apps-index-app"]')
.should('have.length', 1)

cy
.get('[data-cy="apps-index-search-input"]')
.type('qwerty')

cy
.get('[data-cy="apps-index-app"]')
.should('have.length', 0)
})

it('Can show error states in the list', () => {
cy.intercept(
{
method: 'GET',
url: '/parse-dashboard-config.json',
},
getDashboardConfig([
{
appName: 'test1',
},
{
appName: 'test2',
masterKey: 'cos',
},
{
appName: 'test3',
appId: 'cos',
},
{
appName: 'test4',
masterKey: 'cos',
appId: 'cos',
},
{
appName: 'test5',
serverURL: 'http://unavailablehost:1234'
},
{
appName: 'test6',
serverURL: 'http://localhost:1337/parse2'
},
]),
);

cy.visit('/apps')

cy
.get('[data-cy="apps-index-app"]')
.should('have.length', 6)

cy
.get('[data-cy="apps-index-app"]')
.eq(0)
.find('[data-cy="apps-index-app-details"]')
.contains('Server URL: http://localhost:1337/parse')

cy
.get('[data-cy="apps-index-app"]')
.eq(1)
.find('[data-cy="apps-index-app-details"]')
.contains('Server not reachable: unauthorized')

cy
.get('[data-cy="apps-index-app"]')
.eq(2)
.find('[data-cy="apps-index-app-details"]')
.contains('Server not reachable: unauthorized')

cy
.get('[data-cy="apps-index-app"]')
.eq(3)
.find('[data-cy="apps-index-app-details"]')
.contains('Server not reachable: unauthorized')

cy
.get('[data-cy="apps-index-app"]')
.eq(4)
.find('[data-cy="apps-index-app-details"]')
.contains('Server not reachable: unable to connect to server')

cy
.get('[data-cy="apps-index-app"]')
.eq(5)
.find('[data-cy="apps-index-app-details"]')
.contains('Server not reachable: unable to connect to server')
});
})
68 changes: 68 additions & 0 deletions cypress/integration/dashboard.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/// <reference types="cypress" />

import { getDashboardConfig } from '../utils/getDashboardConfig';

describe('Dashboard', () => {
it('Redirects to first app if there is only one', () => {
cy.intercept(
{
method: 'GET',
url: '/parse-dashboard-config.json',
},
getDashboardConfig([
{
appName: 'test1',
},
]),
);

cy.visit('/');

cy
.url()
.should('match', /\/apps\/test1\/browser\/_Role$/);
});

it('Shows loader during loading', () => {
cy.intercept(
{
method: 'GET',
url: '/parse-dashboard-config.json',
},
(req) => {
req.reply({
statusCode: 200,
delay: 250,
body: getDashboardConfig([
{
appName: 'test',
}
]),
})
}
)

cy.visit('/')

cy.get('[data-cy="dashboard-loader"]', {
timeout: 250
});
})

it('c', () => {
cy.intercept(
{
method: 'GET',
url: '/parse-dashboard-config.json',
},
getDashboardConfig([
{
appName: 'test1',
serverURL: 'http://localhost'
},
]),
);

cy.visit('/');
})
})
7 changes: 7 additions & 0 deletions cypress/plugins/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/// <reference types="cypress" />

/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
module.exports = () => {}
Empty file added cypress/support/index.js
Empty file.
14 changes: 14 additions & 0 deletions cypress/utils/getDashboardConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export function getDashboardConfig(apps) {
return {
newFeaturesInLatestVersion: [],
apps: apps.map(app => ({
serverURL: app.serverURL || "http://localhost:1337/parse",
appId: app.appId || "hello",
masterKey: app.masterKey || "world",
appName: app.appName,
iconName: app.iconName || "",
primaryBackgroundColor: app.primaryBackgroundColor || "",
secondaryBackgroundColor: app.secondaryBackgroundColor || "",
})),
};
}
Loading