Merge pull request #5675 from ayshiff/feature/techdocs-e2e
Feature/techdocs e2e
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs': patch
|
||||
'@backstage/plugin-user-settings': patch
|
||||
---
|
||||
|
||||
Add "data-testid" for e2e tests and fix techdocs entity not found error.
|
||||
@@ -23,3 +23,4 @@
|
||||
/.changeset/cost-insights-* @backstage/reviewers @backstage/silver-lining
|
||||
/.changeset/search-* @backstage/techdocs-core
|
||||
/.changeset/techdocs-* @backstage/techdocs-core
|
||||
/cypress/src/integration/plugins/techdocs.spec.ts @backstage/techdocs-core
|
||||
|
||||
@@ -133,3 +133,6 @@ site
|
||||
|
||||
# Sensitive credentials
|
||||
*-credentials.yaml
|
||||
|
||||
# e2e tests
|
||||
cypress/cypress/*
|
||||
|
||||
+3
-1
@@ -262,7 +262,9 @@ catalog:
|
||||
# Backstage example groups and users
|
||||
- type: file
|
||||
target: ../catalog-model/examples/acme-corp.yaml
|
||||
|
||||
# Backstage end-to-end tests of TechDocs
|
||||
- type: file
|
||||
target: ../../cypress/e2e-fixture.catalog.info.yaml
|
||||
scaffolder:
|
||||
# Use to customize default commit author info used when new components are created
|
||||
# defaultAuthor:
|
||||
|
||||
@@ -11,6 +11,7 @@ module.exports = {
|
||||
bundledDependencies: false,
|
||||
},
|
||||
],
|
||||
'jest/valid-expect': 'off',
|
||||
'jest/expect-expect': 'off',
|
||||
'no-restricted-syntax': 'off',
|
||||
},
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
"baseUrl": "http://localhost:7000",
|
||||
"integrationFolder": "./src/integration",
|
||||
"supportFile": "./src/support",
|
||||
"fixturesFolder": "./src/fixures",
|
||||
"fixturesFolder": "./src/fixtures",
|
||||
"pluginsFile": "./src/plugins",
|
||||
"defaultCommandTimeout": 10000
|
||||
"defaultCommandTimeout": 10000,
|
||||
"viewportHeight": 900,
|
||||
"viewportWidth": 1440
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
apiVersion: backstage.io/v1alpha1
|
||||
kind: Component
|
||||
metadata:
|
||||
name: techdocs-e2e-fixture
|
||||
description: Used for end-to-end tests of TechDocs in Backstage.
|
||||
annotations:
|
||||
backstage.io/techdocs-ref: dir:./fixtures
|
||||
spec:
|
||||
type: service
|
||||
lifecycle: experimental
|
||||
owner: user:guest
|
||||
@@ -0,0 +1,3 @@
|
||||
# Home page
|
||||
|
||||
This is a basic documentation used for end-to-end tests.
|
||||
@@ -0,0 +1,109 @@
|
||||
# Sub-page 1
|
||||
|
||||
## Section 1.1
|
||||
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
|
||||
## Section 1.2
|
||||
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
|
||||
## Section 1.3
|
||||
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
@@ -0,0 +1,121 @@
|
||||
# Sub-page 3
|
||||
|
||||
## Section 3.1
|
||||
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
|
||||
## Section 3.2
|
||||
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
|
||||
### Sub-Section 3.2.1
|
||||
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
|
||||
### Sub-Section 3.2.2
|
||||
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
|
||||
## Section 3.3
|
||||
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
@@ -0,0 +1,146 @@
|
||||
# Sub-page 2
|
||||
|
||||
## Section 2.1
|
||||
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
|
||||
## Section 2.2
|
||||
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
|
||||
### Sub-Section 2.2.1
|
||||
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
|
||||
### Sub-Section 2.2.2
|
||||
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
|
||||
## Section 2.3
|
||||
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
To next page!
|
||||
|
||||
[Link to Section 1.1](sub-page-one.md#section-11)
|
||||
@@ -0,0 +1,10 @@
|
||||
site_name: e2e Fixture Documentation
|
||||
site_description: Documentation used for end-to-end tests of TechDocs in Backstage.
|
||||
nav:
|
||||
- Home: index.md
|
||||
- Sub-page 1: sub-page-one.md
|
||||
- Sub-page 2: sub-page-two.md
|
||||
- Nested Sub-pages:
|
||||
- Sub-page 3: sub-page-three.md
|
||||
plugins:
|
||||
- techdocs-core
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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" />
|
||||
import 'os';
|
||||
|
||||
describe('TechDocs', () => {
|
||||
beforeEach(() => {
|
||||
cy.loginAsGuest();
|
||||
cy.mockSockJSNode();
|
||||
cy.interceptTechDocsAPICalls();
|
||||
});
|
||||
|
||||
describe('Navigating to TechDocs', () => {
|
||||
it('should navigate to the TechDocs home page via the primary navigation bar', () => {
|
||||
cy.visit('/');
|
||||
cy.wait(500);
|
||||
|
||||
cy.get('[data-testid="sidebar-root"]')
|
||||
.get('div')
|
||||
.get('a[href="/docs"]')
|
||||
.click();
|
||||
|
||||
cy.contains('Documentation');
|
||||
});
|
||||
|
||||
it('should navigate to the TechDocs home page from the URL', () => {
|
||||
cy.visit('/docs');
|
||||
cy.wait(500);
|
||||
|
||||
cy.contains('Documentation');
|
||||
});
|
||||
|
||||
it('should navigate to a specific TechDocs entity from the "Overview" tab', () => {
|
||||
cy.visit('/docs');
|
||||
cy.contains('techdocs-e2e-fixture')
|
||||
.parents()
|
||||
.eq(2)
|
||||
.contains('Read Docs')
|
||||
.click();
|
||||
|
||||
cy.location().should(loc => {
|
||||
expect(loc.pathname).to.eq(
|
||||
'/docs/default/Component/techdocs-e2e-fixture',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should navigate to a specific TechDocs entity page from a URL', () => {
|
||||
cy.visit('/docs/default/Component/techdocs-e2e-fixture');
|
||||
cy.waitHomePage();
|
||||
|
||||
cy.contains('e2e Fixture Documentation');
|
||||
cy.contains(
|
||||
'Documentation used for end-to-end tests of TechDocs in Backstage.',
|
||||
);
|
||||
cy.getTechDocsShadowRoot().contains('Home page');
|
||||
});
|
||||
|
||||
it('should navigate to a specific TechDocs section from a URL', () => {
|
||||
cy.visit('/docs/default/Component/techdocs-e2e-fixture/sub-page-two');
|
||||
cy.waitSectionTwoPage();
|
||||
|
||||
cy.window().its('scrollY').should('equal', 0);
|
||||
|
||||
cy.getTechDocsShadowRoot().within(() => {
|
||||
cy.contains('Sub-page 2');
|
||||
});
|
||||
});
|
||||
|
||||
it('should navigate to a specific TechDocs fragment from a URL', () => {
|
||||
cy.visit(
|
||||
'/docs/default/Component/techdocs-e2e-fixture/sub-page-two#section-23',
|
||||
);
|
||||
cy.waitSectionTwoPage();
|
||||
|
||||
// This is used to test the post-render behavior of the techdocs Reader
|
||||
cy.wait(500);
|
||||
|
||||
cy.getTechDocsShadowRoot().within(() => {
|
||||
cy.isInViewport('#section-23');
|
||||
});
|
||||
});
|
||||
|
||||
it('should navigate to a wrong TechDocs entity page from a URL', () => {
|
||||
cy.visit('/docs/default/Component/wrong-component');
|
||||
|
||||
cy.get('[data-testid=error]').should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Navigating within TechDocs', () => {
|
||||
it('should navigate to a specific TechDocs page via the navigation bar', () => {
|
||||
cy.visit('/docs/default/Component/techdocs-e2e-fixture');
|
||||
cy.waitHomePage();
|
||||
|
||||
cy.getTechDocsShadowRoot().within(() => {
|
||||
cy.getTechDocsNavigation()
|
||||
.find('> div > div > [data-md-level="0"] > ul > li:nth-child(2) > a')
|
||||
.click();
|
||||
cy.contains('Sub-page 1');
|
||||
cy.window().its('scrollY').should('eq', 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Navigating within a TechDocs page', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/docs/default/Component/techdocs-e2e-fixture/sub-page-two');
|
||||
cy.waitSectionTwoPage();
|
||||
});
|
||||
it('should navigate to a specific fragment within the page via the table of contents - Level 1', () => {
|
||||
return cy.getTechDocsShadowRoot().within(() => {
|
||||
// Section 3
|
||||
cy.getTechDocsTableOfContents().within(() => {
|
||||
cy.get('> div > div > nav > ul > li:nth-child(3) > a').click();
|
||||
});
|
||||
|
||||
cy.isInViewport('#section-23');
|
||||
});
|
||||
});
|
||||
|
||||
it('should navigate to a specific fragment within the page via the table of contents - Level 2', () => {
|
||||
return cy.getTechDocsShadowRoot().within(() => {
|
||||
cy.isNotInViewport('#sub-section-222');
|
||||
// Section 2.2
|
||||
cy.getTechDocsTableOfContents()
|
||||
.find(
|
||||
'> div > div > nav > ul > li:nth-child(2) > nav > ul > li:nth-child(2) > a',
|
||||
)
|
||||
.click();
|
||||
|
||||
cy.isInViewport('#sub-section-222');
|
||||
});
|
||||
});
|
||||
|
||||
it('should navigate to a specific TechDocs page fragment from a link', () => {
|
||||
return cy.getTechDocsShadowRoot().within(() => {
|
||||
cy.get('.md-content > article')
|
||||
.contains('Link to Section 1.1')
|
||||
.click();
|
||||
|
||||
cy.location().should(loc => {
|
||||
expect(loc.pathname).to.eq(
|
||||
'/docs/default/Component/techdocs-e2e-fixture/sub-page-one/',
|
||||
);
|
||||
expect(loc.hash).to.eq('#section-11');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should navigate to the next page within a TechDocs entity', () => {
|
||||
return cy.getTechDocsShadowRoot().within(() => {
|
||||
cy.get('.md-footer-nav__link--next').click();
|
||||
|
||||
cy.location().should(loc => {
|
||||
expect(loc.pathname).to.eq(
|
||||
'/docs/default/Component/techdocs-e2e-fixture/sub-page-three/',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should navigate to the previous page within a TechDocs entity', () => {
|
||||
return cy.getTechDocsShadowRoot().within(() => {
|
||||
cy.get('.md-footer-nav__link--prev').click();
|
||||
|
||||
cy.location().should(loc => {
|
||||
expect(loc.pathname).to.eq(
|
||||
'/docs/default/Component/techdocs-e2e-fixture/sub-page-one/',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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" />
|
||||
import 'os';
|
||||
|
||||
describe('Login', () => {
|
||||
it('should render the login page', () => {
|
||||
cy.visit('/');
|
||||
cy.contains('Select a sign-in method');
|
||||
});
|
||||
|
||||
it('should be able to login', () => {
|
||||
cy.get('button').contains('Enter').click();
|
||||
cy.url().should('include', '/catalog');
|
||||
|
||||
cy.contains('artist-lookup');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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" />
|
||||
import 'os';
|
||||
|
||||
describe('Logout', () => {
|
||||
before(() => {
|
||||
cy.loginAsGuest();
|
||||
});
|
||||
it('should be able to logout', () => {
|
||||
cy.visit('/settings');
|
||||
cy.get('[data-testid="user-settings-menu"]').click();
|
||||
return cy
|
||||
.get('[data-testid="sign-out"]')
|
||||
.click()
|
||||
.then(() => {
|
||||
return expect(
|
||||
localStorage.getItem('@backstage/core:SignInPage:provider'),
|
||||
).to.be.null;
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/* eslint-disable jest/no-standalone-expect */
|
||||
/// <reference types="cypress" />
|
||||
import 'os';
|
||||
|
||||
Cypress.Commands.add('loginAsGuest', () => {
|
||||
cy.visit('/', {
|
||||
onLoad: (win: Window) =>
|
||||
win.localStorage.setItem('@backstage/core:SignInPage:provider', 'guest'),
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('getTechDocsShadowRoot', () => {
|
||||
cy.get('[data-testid="techdocs-content-shadowroot"]').shadow();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('isNotInViewport', element => {
|
||||
cy.get(element).then($el => {
|
||||
const bottom = Cypress.config(`viewportHeight`);
|
||||
const rect = $el[0].getBoundingClientRect();
|
||||
|
||||
if (bottom) {
|
||||
expect(rect.top).to.be.greaterThan(bottom);
|
||||
expect(rect.bottom).to.be.greaterThan(bottom);
|
||||
expect(rect.top).to.be.greaterThan(bottom);
|
||||
expect(rect.bottom).to.be.greaterThan(bottom);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('isInViewport', element => {
|
||||
cy.get(element).then($el => {
|
||||
const bottom = Cypress.config(`viewportHeight`);
|
||||
const rect = $el[0].getBoundingClientRect();
|
||||
|
||||
if (bottom) {
|
||||
expect(rect.top).not.to.be.greaterThan(bottom);
|
||||
expect(rect.bottom).not.to.be.greaterThan(bottom);
|
||||
expect(rect.top).not.to.be.greaterThan(bottom);
|
||||
expect(rect.bottom).not.to.be.greaterThan(bottom);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('getTechDocsTableOfContents', () => {
|
||||
cy.get('[data-md-component="toc"]');
|
||||
});
|
||||
|
||||
Cypress.Commands.add('getTechDocsNavigation', () => {
|
||||
cy.get('[data-md-component="navigation"]');
|
||||
});
|
||||
|
||||
Cypress.Commands.add('mockSockJSNode', () => {
|
||||
cy.intercept('GET', '**/sockjs-node/info**', {
|
||||
body: {
|
||||
websocket: true,
|
||||
origins: ['*:*'],
|
||||
cookie_needed: false,
|
||||
entropy: 2882389500,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('interceptTechDocsAPICalls', () => {
|
||||
cy.intercept(
|
||||
'GET',
|
||||
'**/techdocs/metadata/entity/default/Component/techdocs-e2e-fixture',
|
||||
).as('entityMetadata');
|
||||
|
||||
cy.intercept(
|
||||
'GET',
|
||||
'**/techdocs/metadata/techdocs/default/Component/techdocs-e2e-fixture',
|
||||
).as('techdocsMetadata');
|
||||
|
||||
cy.intercept(
|
||||
'GET',
|
||||
'**/techdocs/sync/default/Component/techdocs-e2e-fixture',
|
||||
).as('syncEntity');
|
||||
|
||||
cy.intercept(
|
||||
'GET',
|
||||
'**/techdocs/static/docs/default/Component/techdocs-e2e-fixture/sub-page-two/index.html',
|
||||
).as('sectionTwoHTML');
|
||||
|
||||
cy.intercept(
|
||||
'GET',
|
||||
'**/techdocs/static/docs/default/Component/techdocs-e2e-fixture/index.html',
|
||||
).as('homeHTML');
|
||||
});
|
||||
|
||||
Cypress.Commands.add('waitSectionTwoPage', () => {
|
||||
cy.wait([
|
||||
'@entityMetadata',
|
||||
'@syncEntity',
|
||||
'@techdocsMetadata',
|
||||
'@sectionTwoHTML',
|
||||
]);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('waitHomePage', () => {
|
||||
cy.wait(['@entityMetadata', '@syncEntity', '@techdocsMetadata', '@homeHTML']);
|
||||
});
|
||||
@@ -14,12 +14,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
/// <reference types="cypress" />
|
||||
|
||||
Cypress.Commands.add('loginAsGuest', () => {
|
||||
cy.visit('/', {
|
||||
onLoad: (win: Window) =>
|
||||
win.localStorage.setItem('@backstage/core:SignInPage:provider', 'guest'),
|
||||
});
|
||||
});
|
||||
|
||||
export {};
|
||||
import './commands';
|
||||
|
||||
Vendored
+50
@@ -22,5 +22,55 @@ declare namespace Cypress {
|
||||
* @example cy.loginAsGuests
|
||||
*/
|
||||
loginAsGuest(): Chainable<Element>;
|
||||
/**
|
||||
* Get the TechDocs shadow root element
|
||||
* @example cy.getTechDocsShadowRoot
|
||||
*/
|
||||
getTechDocsShadowRoot(): Chainable<Element>;
|
||||
/**
|
||||
* Mock TechDocs backend API
|
||||
* @example cy.mockTechDocs
|
||||
*/
|
||||
mockTechDocs(): void;
|
||||
/**
|
||||
* Get the TechDocs table of contents element
|
||||
* @example cy.getTechDocsShadowRoot
|
||||
*/
|
||||
getTechDocsTableOfContents(): Chainable<Element>;
|
||||
/**
|
||||
* Get the TechDocs navigation element
|
||||
* @example cy.getTechDocsNavigation
|
||||
*/
|
||||
getTechDocsNavigation(): Chainable<Element>;
|
||||
/**
|
||||
* Intercept the TechDocs API calls
|
||||
* @example cy.interceptTechDocsAPICalls
|
||||
*/
|
||||
interceptTechDocsAPICalls(): Chainable<Element>;
|
||||
/**
|
||||
* Mock SockJS-Node call
|
||||
* @example cy.mockSockJSNode
|
||||
*/
|
||||
mockSockJSNode(): Chainable<Element>;
|
||||
/**
|
||||
* Wait TechDocs API response for home page
|
||||
* @example cy.waitHomePage
|
||||
*/
|
||||
waitHomePage(): Chainable<Element>;
|
||||
/**
|
||||
* Wait TechDocs API response for Section 2 page
|
||||
* @example cy.waitSectionTwoPage
|
||||
*/
|
||||
waitSectionTwoPage(): Chainable<Element>;
|
||||
/**
|
||||
* Check if the element is in viewport
|
||||
* @example cy.isInViewport
|
||||
*/
|
||||
isInViewport(element: string): Chainable<Element>;
|
||||
/**
|
||||
* Check if the element is not in viewport
|
||||
* @example cy.isNotInViewport
|
||||
*/
|
||||
isNotInViewport(element: string): Chainable<Element>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,11 @@ export function ErrorPage(props: IErrorPageProps) {
|
||||
<Grid container spacing={0} className={classes.container}>
|
||||
<MicDrop />
|
||||
<Grid item xs={12} sm={8} md={4}>
|
||||
<Typography variant="body1" className={classes.subtitle}>
|
||||
<Typography
|
||||
data-testid="error"
|
||||
variant="body1"
|
||||
className={classes.subtitle}
|
||||
>
|
||||
ERROR {status}: {statusMessage}
|
||||
</Typography>
|
||||
<Typography variant="body1" className={classes.subtitle}>
|
||||
|
||||
@@ -88,6 +88,7 @@ export function HeaderTabs(props: HeaderTabsProps) {
|
||||
{tabs.map((tab, index) => (
|
||||
<TabUI
|
||||
{...tab.tabProps}
|
||||
data-testid={`header-tab-${index}`}
|
||||
label={tab.label}
|
||||
key={tab.id}
|
||||
value={index}
|
||||
|
||||
@@ -62,6 +62,7 @@ export const DocsCardGrid = ({
|
||||
name: toLowerMaybe(entity.metadata.name),
|
||||
})}
|
||||
color="primary"
|
||||
data-testid="read_docs"
|
||||
>
|
||||
Read Docs
|
||||
</Button>
|
||||
|
||||
@@ -108,7 +108,7 @@ const CustomPanel = ({
|
||||
) : null}
|
||||
</ContentHeader>
|
||||
<div className={classes.panelContainer}>
|
||||
<Panel entities={shownEntities} />
|
||||
<Panel data-testid="techdocs-custom-panel" entities={shownEntities} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
@@ -182,7 +182,7 @@ export const TechDocsCustomHome = ({
|
||||
label,
|
||||
}))}
|
||||
/>
|
||||
<Content>
|
||||
<Content data-testid="techdocs-content">
|
||||
{currentTabConfig.panels.map((config, index) => (
|
||||
<CustomPanel
|
||||
key={index}
|
||||
|
||||
@@ -19,6 +19,7 @@ import { useParams } from 'react-router-dom';
|
||||
import { useAsync } from 'react-use';
|
||||
import { techdocsApiRef } from '../../api';
|
||||
import { Reader } from './Reader';
|
||||
import { TechDocsNotFound } from './TechDocsNotFound';
|
||||
import { TechDocsPageHeader } from './TechDocsPageHeader';
|
||||
|
||||
import { Content, Page } from '@backstage/core-components';
|
||||
@@ -38,14 +39,19 @@ export const TechDocsPage = () => {
|
||||
return Promise.resolve(undefined);
|
||||
}, [kind, namespace, name, techdocsApi, documentReady]);
|
||||
|
||||
const { value: entityMetadataValue } = useAsync(() => {
|
||||
return techdocsApi.getEntityMetadata({ kind, namespace, name });
|
||||
}, [kind, namespace, name, techdocsApi]);
|
||||
const { value: entityMetadataValue, error: entityMetadataError } =
|
||||
useAsync(() => {
|
||||
return techdocsApi.getEntityMetadata({ kind, namespace, name });
|
||||
}, [kind, namespace, name, techdocsApi]);
|
||||
|
||||
const onReady = useCallback(() => {
|
||||
setDocumentReady(true);
|
||||
}, [setDocumentReady]);
|
||||
|
||||
if (entityMetadataError) {
|
||||
return <TechDocsNotFound errorMessage={entityMetadataError.message} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Page themeId="documentation">
|
||||
<TechDocsPageHeader
|
||||
|
||||
@@ -39,11 +39,15 @@ export const UserSettingsMenu = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<IconButton aria-label="more" onClick={handleOpen}>
|
||||
<IconButton
|
||||
data-testid="user-settings-menu"
|
||||
aria-label="more"
|
||||
onClick={handleOpen}
|
||||
>
|
||||
<MoreVertIcon />
|
||||
</IconButton>
|
||||
<Menu anchorEl={anchorEl} open={open} onClose={handleClose}>
|
||||
<MenuItem onClick={() => identityApi.signOut()}>
|
||||
<MenuItem data-testid="sign-out" onClick={() => identityApi.signOut()}>
|
||||
<ListItemIcon>
|
||||
<SignOutIcon />
|
||||
</ListItemIcon>
|
||||
|
||||
@@ -42,6 +42,7 @@ const getFilesToLint = () => {
|
||||
|
||||
// Note this ignore list only applies locally, CI runs `.github/workflows/docs-quality-checker.yml`
|
||||
const ignored = ['', 'ADOPTERS.md', 'OWNERS.md'];
|
||||
|
||||
return execSync(command, {
|
||||
stdio: ['ignore', 'pipe', 'inherit'],
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user