docs: init cypress test e2e

Signed-off-by: jffarge <jf@dagger.io>
This commit is contained in:
jffarge 2021-07-02 11:23:12 +02:00
parent 795430024b
commit 868339e174
15 changed files with 1091 additions and 56 deletions

View File

@ -120,3 +120,34 @@ jobs:
- name: Universe Test
run: |
make universe-test
cypress-run:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Cypress run
uses: cypress-io/github-action@v2
env:
REACT_APP_CLIENT_ID: 123
REACT_APP_CLIENT_SECRET: 123
REACT_APP_DAGGER_SITE_URI: https://dagger.io
REACT_APP_API_PROXY_ENABLE: false
REACT_APP_AMPLITUDE_ID: 123
with:
config: chromeWebSecurity=false
start: |
yarn start
yarn start:withAuth
working-directory: ./website
- uses: actions/upload-artifact@v1
if: failure()
with:
name: cypress-screenshots
path: website/cypress/screenshots
# Test run video was always captured, so this action uses "always()" condition
- uses: actions/upload-artifact@v1
if: always()
with:
name: cypress-videos
path: website/cypress/videos

9
website/.prettierrc Normal file
View File

@ -0,0 +1,9 @@
{
"arrowParens": "always",
"bracketSpacing": false,
"jsxBracketSameLine": true,
"printWidth": 80,
"proseWrap": "never",
"singleQuote": true,
"trailingComma": "all"
}

4
website/cypress.json Normal file
View File

@ -0,0 +1,4 @@
{
"chromeWebSecurity": false,
"video": false
}

View File

@ -0,0 +1,4 @@
{
"message": "Bad credentials",
"documentation_url": "https://docs.github.com/rest"
}

View File

@ -0,0 +1,5 @@
{
"error":"bad_verification_code",
"error_description":"The code passed is incorrect or expired.",
"error_uri":"https://docs.github.com/apps/managing-oauth-apps/troubleshooting-oauth-app-access-token-request-errors/#bad-verification-code"
}

View File

@ -0,0 +1,53 @@
describe('Visit Docs website', function() {
it('Visit docs website without authentication', function() {
cy.visit('http://localhost:3000')
cy.get('[data-cy="cy-signin"]').should('not.exist')
}),
it('Visit docs website with authentication', function() {
cy.visit('http://localhost:3001')
cy.get('[data-cy="cy-signin"]').should('exist')
})
context('When user is authenticated', function() {
beforeEach(() => {
cy.setLocalStorage('user', "{\"permission\":true,\"login\":\"slumbering\"}")
cy.intercept('/t', 'success').as('logAmplitude')
cy.visit(('http://localhost:3001'))
})
it('Visit docs website with a valid authenticated user', function() {
cy.get('[data-cy=cy-doc-content]').should('exist')
})
it('log to amplitude when user visit another page', function() {
cy.get('[data-cy=cy-doc-content]').should('exist')
cy.get('.menu > :nth-child(2) > :nth-child(2) > .menu__link').click()
})
})
context('When user is not authorized', function() {
it('Redirect user after unsuccessful sign in', function() {
cy.intercept('**/login/oauth/access_token?code=jergub54545&client_id=123&client_secret=321', {fixture: 'bad_verification.code.json'})
cy.intercept('**/user', (req) => {
req.continue((res) => {
expect(res.statusCode).to.be.equal(401)
})
})
cy.visit('http://localhost:3001?code=jergub54545')
cy.get('[data-cy=cy-page-redirect]').should('exist')
// cy.wait(10000)
// cy.location().should((location) => {
// expect(location.host).to.eq('dagger.io')
// })
})
it('Visit docs website with a user not authorized', function() {
cy.setLocalStorage('user', "{\"permission\":false,\"login\":\"slumbering\"}")
cy.visit('http://localhost:3001')
cy.get('[data-cy=cy-page-redirect]').should('exist')
cy.intercept('/t', 'success')
})
})
})

View File

@ -0,0 +1,22 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}

View File

@ -0,0 +1,26 @@
// ***********************************************
// 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 will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
import "cypress-localstorage-commands"

View File

@ -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')

4
website/cypress/videos/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -5,7 +5,7 @@
"scripts": {
"docusaurus": "docusaurus",
"start": "OAUTH_ENABLE=false docusaurus start",
"start:withAuth": "OAUTH_ENABLE=true docusaurus start",
"start:withAuth": "OAUTH_ENABLE=true docusaurus start --port=3001",
"build": "OAUTH_ENABLE=true docusaurus build",
"build:withoutAuth": "OAUTH_ENABLE=false docusaurus build",
"swizzle": "docusaurus swizzle",
@ -13,7 +13,9 @@
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids"
"write-heading-ids": "docusaurus write-heading-ids",
"start-server": "concurrently \"OAUTH_ENABLE=false yarn docusaurus start --port=3000 --no-open\" \"OAUTH_ENABLE=true yarn docusaurus start --port=3001 --no-open\"",
"ci": "start-server-and-test 'yarn start-server' '3000|3001' 'yarn run cypress run'"
},
"dependencies": {
"@docusaurus/core": "2.0.0-beta.2",
@ -42,5 +44,11 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"concurrently": "^6.2.0",
"cypress": "^7.6.0",
"cypress-localstorage-commands": "^1.4.5",
"start-server-and-test": "^1.12.5"
}
}

View File

@ -4,10 +4,12 @@ import style from './DocPageAuthentication.module.css'
export default function DocAuthentication() {
return (
<div className={style.container}>
<div data-cy="cy-signin" className={style.container}>
<h1 className={style.h1}>Welcome on Dagger documentation</h1>
<p>Please Sign In to Github to get access to the doc</p>
<GithubLoginButton className={style.btn__github} onClick={() => window.location.href = process.env.REACT_APP_GITHUB_AUTHORIZE_URI} />
<div data-cy="cy-btn-signin">
<GithubLoginButton className={style.btn__github} onClick={() => window.location.href = process.env.REACT_APP_GITHUB_AUTHORIZE_URI} />
</div>
</div>
)
}

View File

@ -11,7 +11,7 @@ export default function DocPageRedirect() {
}, [])
return (
<div className={`container ${style.wrapper}`}>
<div data-cy="cy-page-redirect" className={`container ${style.wrapper}`}>
<div className={`row ${style.row}`}>
<div className="col col--4 col--offset-2">
<h1 className={style.h1}>Oups!</h1>

View File

@ -13,15 +13,15 @@ import DocSidebar from '@theme/DocSidebar';
import MDXComponents from '@theme/MDXComponents';
import NotFound from '@theme/NotFound';
import IconArrow from '@theme/IconArrow';
import { matchPath } from '@docusaurus/router';
import { translate } from '@docusaurus/Translate';
import {matchPath} from '@docusaurus/router';
import {translate} from '@docusaurus/Translate';
import clsx from 'clsx';
import styles from './styles.module.css';
import { ThemeClassNames, docVersionSearchTag } from '@docusaurus/theme-common';
import DocPageCustom from '../../components/DocPageCustom'
import {ThemeClassNames, docVersionSearchTag} from '@docusaurus/theme-common';
import DocPageCustom from '../../components/DocPageCustom';
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
function getSidebar({ versionMetadata, currentDocRoute }) {
function getSidebar({versionMetadata, currentDocRoute}) {
function addTrailingSlash(str) {
return str.endsWith('/') ? str : `${str}/`;
}
@ -30,7 +30,7 @@ function getSidebar({ versionMetadata, currentDocRoute }) {
return str.endsWith('/') ? str.slice(0, -1) : str;
}
const { permalinkToSidebar, docsSidebars } = versionMetadata; // With/without trailingSlash, we should always be able to get the appropriate sidebar
const {permalinkToSidebar, docsSidebars} = versionMetadata; // With/without trailingSlash, we should always be able to get the appropriate sidebar
// note: docs plugin permalinks currently never have trailing slashes
// trailingSlash is handled globally at the framework level, not plugin level
@ -45,10 +45,10 @@ function getSidebar({ versionMetadata, currentDocRoute }) {
};
}
function DocPageContent({ currentDocRoute, versionMetadata, children }) {
const { siteConfig, isClient } = useDocusaurusContext();
const { pluginId, version } = versionMetadata;
const { sidebarName, sidebar } = getSidebar({
function DocPageContent({currentDocRoute, versionMetadata, children}) {
const {siteConfig, isClient} = useDocusaurusContext();
const {pluginId, version} = versionMetadata;
const {sidebarName, sidebar} = getSidebar({
versionMetadata,
currentDocRoute,
});
@ -149,7 +149,7 @@ function DocPageContent({ currentDocRoute, versionMetadata, children }) {
function DocPage(props) {
const {
route: { routes: docRoutes },
route: {routes: docRoutes},
versionMetadata,
location,
} = props;
@ -159,9 +159,12 @@ function DocPage(props) {
const userAgent = ExecutionEnvironment.canUseDOM ? navigator.userAgent : null;
// DocPage Swizzle
const [userAccessStatus, setUserAccessStatus] = useState((() => {
if (typeof window !== "undefined") return JSON.parse(window.localStorage.getItem('user'))
})())
const [userAccessStatus, setUserAccessStatus] = useState(
(() => {
if (typeof window !== 'undefined')
return JSON.parse(window.localStorage.getItem('user'));
})(),
);
useEffect(() => {
import('amplitude-js').then(amplitude => {
@ -191,9 +194,11 @@ function DocPage(props) {
<DocPageContent
currentDocRoute={currentDocRoute}
versionMetadata={versionMetadata}>
{renderRoutes(docRoutes, {
versionMetadata,
})}
<div data-cy="cy-doc-content">
{renderRoutes(docRoutes, {
versionMetadata,
})}
</div>
</DocPageContent>
);
}

File diff suppressed because it is too large Load Diff