Merge pull request #9546 from backstage/emmaindal/techdocs-cli-tests

[TechDocs CLI] adding cypress testing
This commit is contained in:
Emma Indal
2022-02-21 15:54:53 +01:00
committed by GitHub
30 changed files with 1235 additions and 30 deletions
+45 -9
View File
@@ -40,8 +40,25 @@ yarn start
yarn techdocs-cli:dev [...options]
```
### Using an example docs project
For the purpose of local development, we have created an example documentation project. You are of course also free to create your own local test site - all it takes is a `docs/index.md` and an `mkdocs.yml` in a directory.
```sh
cd packages/techdocs-cli/src/example-docs
# To get a view of your docs in Backstage, use:
techdocs-cli serve
# To view the raw mkdocs site (without Backstage), use:
techdocs-cli serve:mkdocs
```
### Testing
#### E2E tests
Running unit tests requires mkdocs to be installed locally:
```sh
@@ -51,18 +68,37 @@ pip install mkdocs-techdocs-core
Then run `yarn test`.
### Use an example docs project
#### Cypress (Integration and Visual regression) tests
We have created an [example documentation project](https://github.com/backstage/techdocs-container/tree/main/mock-docs) and it's shipped with [techdocs-container](https://github.com/backstage/techdocs-container) repository, for the purpose of local development. But you are free to create your own local test site. All it takes is a `docs/index.md` and `mkdocs.yml` in a directory.
Running cypress tests requires you to run the CLI locally against our example docs.
Run the local version of techdocs-cli against the example docs:
```sh
git clone https://github.com/backstage/techdocs-container.git
# From the root of this repository run
# NOTE: This will build the techdocs-cli-embedded-app and copy the output into the cli dist directory
yarn build --scope @techdocs/cli
cd techdocs-container/mock-docs
# Navigate to the example project
cd packages/techdocs-cli/src/example-docs
# To get a view of your docs in Backstage, use:
techdocs-cli serve
# To view the raw mkdocs site (without Backstage), use:
techdocs-cli serve:mkdocs
# Now execute the techdocs-cli serve command
../../bin/techdocs-cli serve
```
In another shell, run the cypress tests:
```sh
# From the root of the project, navigate to the techdocs-cli package
cd packages/techdocs-cli
# Run tests
yarn test:cypress
```
This will launch a cypress app where you can run the two different tests:
- `backstage_serve` - will run against the backstage server
- `mkdocs_serve` - will run test against the mkdocs server
> If its the first time you run Cypress, it will run a "Verifying Cypress can run" step. This step can result in a "Cypress verification timed out" error. If that is the case, let the verification step run and then run the command again and it should succeed.
+17
View File
@@ -0,0 +1,17 @@
{
"env": {
"mkDocsBaseUrl": "http://localhost:8000",
"backstageBaseUrl": "http://localhost:3000",
"cypress-plugin-snapshots": {
"autoCleanUp": false,
"imageConfig": {
"resizeDevicePixelRatio": true,
"threshold": 0.01
}
}
},
"viewportWidth": 1920,
"viewportHeight": 1080,
"includeShadowDom": true,
"ignoreTestFiles": ["**/__snapshots__/*", "**/__image_snapshots__/*"]
}
@@ -0,0 +1,21 @@
{
"plugins": ["cypress"],
"extends": ["plugin:cypress/recommended"],
"rules": {
"jest/expect-expect": [
"error",
{
"assertFunctionNames": ["expect", "cy.contains", "cy.document"]
}
],
"import/no-extraneous-dependencies": [
"error",
{
"devDependencies": true,
"optionalDependencies": true,
"peerDependencies": true,
"bundledDependencies": true
}
]
}
}
@@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}
@@ -0,0 +1,58 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/// <reference types="cypress" />
describe('TechDocs Live Preview - Backstage Serve', () => {
it('successfully serves documentation', () => {
cy.visit(`${Cypress.env('backstageBaseUrl')}/docs/default/component/local`);
cy.contains('hello mock docs');
});
it('successfully navigates to sub page of documentation', () => {
cy.contains('SubDocs').click();
cy.contains('Home 2').click();
cy.contains(
'This is an md file in another docs folder using the MkDocs Monorepo Plugin',
);
});
it('successfully renders all Backstage main elements', () => {
cy.contains('header', 'Live preview environment');
cy.get('[data-testid="sidebar-root"]')
.children()
.should('have.length.gt', 0);
});
it('successfully renders all extracted MkDocs main elements', () => {
// as it gets replaced by Backstage header
cy.get('.md-header').should('have.length', 0);
cy.get('.md-main').should('have.length', 1);
cy.contains(
'.md-main',
'This is an md file in another docs folder using the MkDocs Monorepo Plugin',
);
cy.get('.md-sidebar.md-sidebar--primary').should('have.length', 1);
cy.get('.md-sidebar.md-sidebar--primary').should('have.length', 1);
cy.get('.md-footer').should('have.length', 1);
});
it('toMatchImageSnapshot - Backstage TechDocs Page', () => {
cy.visit(
`${Cypress.env('backstageBaseUrl')}/docs/default/component/local`,
).then(() => {
cy.document().toMatchImageSnapshot();
});
});
});
@@ -0,0 +1,48 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/// <reference types="cypress" />
describe('TechDocs Live Preview - MkDocs Serve', () => {
it('successfully serves documentation', () => {
cy.visit(Cypress.env('mkDocsBaseUrl'));
cy.contains('hello mock docs');
});
it('successfully navigates to sub page of documentation', () => {
cy.contains('SubDocs').click();
cy.contains('Home 2').click();
cy.contains(
'This is an md file in another docs folder using the MkDocs Monorepo Plugin',
);
});
it('successfully renders all main elements', () => {
cy.get('.md-header').should('have.length', 1);
cy.get('.md-main').should('have.length', 1);
cy.contains(
'.md-main',
'This is an md file in another docs folder using the MkDocs Monorepo Plugin',
);
cy.get('.md-sidebar.md-sidebar--primary').should('have.length', 1);
cy.get('.md-sidebar.md-sidebar--primary').should('have.length', 1);
cy.get('.md-footer').should('have.length', 1);
});
it('toMatchImageSnapshot - MkDocs Page', () => {
cy.visit(Cypress.env('mkDocsBaseUrl')).then(() => {
cy.document().toMatchImageSnapshot();
});
});
});
@@ -0,0 +1,41 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// ***********************************************************
// 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)
const { initPlugin } = require('cypress-plugin-snapshots/plugin');
/**
* @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
initPlugin(on, config);
return config;
};
@@ -0,0 +1,40 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// 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) => { ... })
@@ -0,0 +1,36 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// 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';
import 'cypress-plugin-snapshots/commands';
// Alternatively you can use CommonJS syntax:
// require('./commands')
+4 -1
View File
@@ -30,6 +30,7 @@
"test": "backstage-cli package test --testPathIgnorePatterns=src/e2e.test.ts",
"test:e2e": "backstage-cli test src/e2e.test.ts",
"test:e2e:ci": "backstage-cli test --watchAll=false --ci src/e2e.test.ts",
"test:cypress": "cypress open",
"prepack": "./scripts/prepack.sh"
},
"bin": {
@@ -44,9 +45,11 @@
"@types/node": "^14.14.32",
"@types/serve-handler": "^6.1.0",
"@types/webpack-env": "^1.15.3",
"techdocs-cli-embedded-app": "link:../techdocs-cli-embedded-app",
"cypress": "^7.3.0",
"cypress-plugin-snapshots": "^1.4.4",
"find-process": "^1.4.5",
"nodemon": "^2.0.2",
"techdocs-cli-embedded-app": "link:../techdocs-cli-embedded-app",
"ts-node": "^10.0.0"
},
"files": [
+1 -1
View File
@@ -23,4 +23,4 @@ TECHDOCS_CLI_EMBEDDED_APP_DIR="$TECHDOCS_CLI_DIR"/../techdocs-cli-embedded-app
echo "🚚 Copying embedded app into dist/embedded-app"
rm -rf "$TECHDOCS_CLI_DIR"/dist/embedded-app
cp -r "$TECHDOCS_CLI_EMBEDDED_APP_DIR"/dist "$TECHDOCS_CLI_DIR"/dist/embedded-app
echo "🏁 Ready!"
echo "🏁 Finished copying embedded app into dist/embedded-app!"
+1 -1
View File
@@ -58,7 +58,7 @@ const timeout = 25000;
jest.setTimeout(timeout * 2);
describe('end-to-end', () => {
const cwd = path.resolve(__dirname, 'fixture');
const cwd = path.resolve(__dirname, 'example-docs');
afterEach(async () => {
// On Windows the pid of a spawned process may be wrong
@@ -0,0 +1 @@
site/
@@ -0,0 +1,92 @@
## hello mock docs
!!! test
Testing something
Abbreviations:
Some text about MOCDOC
This is a paragraph.
{: #test_id .test_class }
Apple
: A fruit.
```javascript
import { test } from 'something';
const addThingToThing = (a, b) a + b;
```
- [abc](#abc)
- [xyz](#xyz)
## abc
This is a b c.
## xyz
This is x y z.
# Emojis
:bulb: :smile:
# Code blocks
```javascript
import { test } from 'something';
const addThingToThing = (a, b) a + b;
```
# Grouped Code blocks
=== "JavaScript"
```javascript
import { test } from 'something';
const addThingToThing = (a, b) a + b;
```
=== "Java"
```java
public void function() {
test();
}
```
```java tab="java"
public void function() {
test();
}
```
```java tab="java 2"
public void function() {
test();
}
```
# MDX truly sane lists
- attributes
- customer
- first_name
- test
- family_name
- email
- person
- first_name
- family_name
- birth_date
- subscription_id
- request
<!-- prettier-ignore -->
*[MOCDOC]: Mock Documentation
@@ -2,7 +2,9 @@ site_name: docs-test-fixture
site_description: Documentation site test fixture
nav:
- HOME: README.md
- Home: index.md
- SubDocs: '!include ./sub-docs/mkdocs.yml'
- Plugins: '*include ./plugins/*/mkdocs.yml'
plugins:
- techdocs-core
@@ -0,0 +1,4 @@
# Plugin A
This is a description of Plugin A. This file exists to prove that glob'd
includes using the `*include` syntax work as expected.
@@ -0,0 +1,5 @@
site_name: Plugin A
site_description: A description of Plugin A
nav:
- Introduction: index.md
@@ -0,0 +1,4 @@
# Plugin B
This is a description of Plugin B. This file exists to prove that glob'd
includes using the `*include` syntax work as expected.
@@ -0,0 +1,5 @@
site_name: Plugin B
site_description: A description of Plugin B
nav:
- Introduction: index.md
@@ -0,0 +1 @@
### This is an md file in another docs folder using the [MkDocs Monorepo Plugin](https://github.com/spotify/mkdocs-monorepo-plugin)
@@ -0,0 +1,4 @@
site_name: subdocs
nav:
- Home 2: 'index.md'
@@ -1 +0,0 @@
# Test Fixture