diff --git a/.changeset/cold-bags-admire.md b/.changeset/cold-bags-admire.md
new file mode 100644
index 0000000000..98191958eb
--- /dev/null
+++ b/.changeset/cold-bags-admire.md
@@ -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.
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 0854635a2b..b637524a52 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -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
diff --git a/.gitignore b/.gitignore
index 57ad74c5cc..8c37280023 100644
--- a/.gitignore
+++ b/.gitignore
@@ -133,3 +133,6 @@ site
# Sensitive credentials
*-credentials.yaml
+
+# e2e tests
+cypress/cypress/*
diff --git a/app-config.yaml b/app-config.yaml
index 3e2ab8471d..d2c8bf8074 100644
--- a/app-config.yaml
+++ b/app-config.yaml
@@ -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:
diff --git a/cypress/.eslintrc.js b/cypress/.eslintrc.js
index d7498649a0..a77de4a629 100644
--- a/cypress/.eslintrc.js
+++ b/cypress/.eslintrc.js
@@ -11,6 +11,7 @@ module.exports = {
bundledDependencies: false,
},
],
+ 'jest/valid-expect': 'off',
'jest/expect-expect': 'off',
'no-restricted-syntax': 'off',
},
diff --git a/cypress/cypress.json b/cypress/cypress.json
index ebbbe59901..3ef3df8e65 100644
--- a/cypress/cypress.json
+++ b/cypress/cypress.json
@@ -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
}
diff --git a/cypress/e2e-fixture.catalog.info.yaml b/cypress/e2e-fixture.catalog.info.yaml
new file mode 100644
index 0000000000..31502e415d
--- /dev/null
+++ b/cypress/e2e-fixture.catalog.info.yaml
@@ -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
diff --git a/cypress/fixtures/docs/index.md b/cypress/fixtures/docs/index.md
new file mode 100644
index 0000000000..d7ff14b46d
--- /dev/null
+++ b/cypress/fixtures/docs/index.md
@@ -0,0 +1,3 @@
+# Home page
+
+This is a basic documentation used for end-to-end tests.
diff --git a/cypress/fixtures/docs/sub-page-one.md b/cypress/fixtures/docs/sub-page-one.md
new file mode 100644
index 0000000000..7c451efeb5
--- /dev/null
+++ b/cypress/fixtures/docs/sub-page-one.md
@@ -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!
diff --git a/cypress/fixtures/docs/sub-page-three.md b/cypress/fixtures/docs/sub-page-three.md
new file mode 100644
index 0000000000..e9a439ed98
--- /dev/null
+++ b/cypress/fixtures/docs/sub-page-three.md
@@ -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!
diff --git a/cypress/fixtures/docs/sub-page-two.md b/cypress/fixtures/docs/sub-page-two.md
new file mode 100644
index 0000000000..eb2344e9c3
--- /dev/null
+++ b/cypress/fixtures/docs/sub-page-two.md
@@ -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)
diff --git a/cypress/fixtures/mkdocs.yml b/cypress/fixtures/mkdocs.yml
new file mode 100644
index 0000000000..2362fab898
--- /dev/null
+++ b/cypress/fixtures/mkdocs.yml
@@ -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
diff --git a/cypress/src/integration/integrations.ts b/cypress/src/integration/integrations.spec.ts
similarity index 100%
rename from cypress/src/integration/integrations.ts
rename to cypress/src/integration/integrations.spec.ts
diff --git a/cypress/src/integration/catalog.ts b/cypress/src/integration/plugins/catalog.spec.ts
similarity index 100%
rename from cypress/src/integration/catalog.ts
rename to cypress/src/integration/plugins/catalog.spec.ts
diff --git a/cypress/src/integration/plugins/techdocs.spec.ts b/cypress/src/integration/plugins/techdocs.spec.ts
new file mode 100644
index 0000000000..0edd7b15ff
--- /dev/null
+++ b/cypress/src/integration/plugins/techdocs.spec.ts
@@ -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.
+ */
+///
+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/',
+ );
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/cypress/src/integration/user/login.spec.ts b/cypress/src/integration/user/login.spec.ts
new file mode 100644
index 0000000000..25be6e8d4b
--- /dev/null
+++ b/cypress/src/integration/user/login.spec.ts
@@ -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.
+ */
+///
+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');
+ });
+});
diff --git a/cypress/src/integration/user/logout.spec.ts b/cypress/src/integration/user/logout.spec.ts
new file mode 100644
index 0000000000..2d37cb63e5
--- /dev/null
+++ b/cypress/src/integration/user/logout.spec.ts
@@ -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.
+ */
+///
+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;
+ });
+ });
+});
diff --git a/cypress/src/support/commands.ts b/cypress/src/support/commands.ts
new file mode 100644
index 0000000000..3c8456fcbd
--- /dev/null
+++ b/cypress/src/support/commands.ts
@@ -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 */
+///
+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']);
+});
diff --git a/cypress/src/support/index.ts b/cypress/src/support/index.ts
index ebfcb04d03..6d1051a793 100644
--- a/cypress/src/support/index.ts
+++ b/cypress/src/support/index.ts
@@ -14,12 +14,4 @@
* limitations under the License.
*/
///
-
-Cypress.Commands.add('loginAsGuest', () => {
- cy.visit('/', {
- onLoad: (win: Window) =>
- win.localStorage.setItem('@backstage/core:SignInPage:provider', 'guest'),
- });
-});
-
-export {};
+import './commands';
diff --git a/cypress/src/types.d.ts b/cypress/src/types.d.ts
index fff4fe29e4..838f5571ed 100644
--- a/cypress/src/types.d.ts
+++ b/cypress/src/types.d.ts
@@ -22,5 +22,55 @@ declare namespace Cypress {
* @example cy.loginAsGuests
*/
loginAsGuest(): Chainable;
+ /**
+ * Get the TechDocs shadow root element
+ * @example cy.getTechDocsShadowRoot
+ */
+ getTechDocsShadowRoot(): Chainable;
+ /**
+ * Mock TechDocs backend API
+ * @example cy.mockTechDocs
+ */
+ mockTechDocs(): void;
+ /**
+ * Get the TechDocs table of contents element
+ * @example cy.getTechDocsShadowRoot
+ */
+ getTechDocsTableOfContents(): Chainable;
+ /**
+ * Get the TechDocs navigation element
+ * @example cy.getTechDocsNavigation
+ */
+ getTechDocsNavigation(): Chainable;
+ /**
+ * Intercept the TechDocs API calls
+ * @example cy.interceptTechDocsAPICalls
+ */
+ interceptTechDocsAPICalls(): Chainable;
+ /**
+ * Mock SockJS-Node call
+ * @example cy.mockSockJSNode
+ */
+ mockSockJSNode(): Chainable;
+ /**
+ * Wait TechDocs API response for home page
+ * @example cy.waitHomePage
+ */
+ waitHomePage(): Chainable;
+ /**
+ * Wait TechDocs API response for Section 2 page
+ * @example cy.waitSectionTwoPage
+ */
+ waitSectionTwoPage(): Chainable;
+ /**
+ * Check if the element is in viewport
+ * @example cy.isInViewport
+ */
+ isInViewport(element: string): Chainable;
+ /**
+ * Check if the element is not in viewport
+ * @example cy.isNotInViewport
+ */
+ isNotInViewport(element: string): Chainable;
}
}
diff --git a/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx b/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx
index f4b2960f96..87eebdb729 100644
--- a/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx
+++ b/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx
@@ -57,7 +57,11 @@ export function ErrorPage(props: IErrorPageProps) {
-
+
ERROR {status}: {statusMessage}
diff --git a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx
index 0fe3cd967e..3468439ade 100644
--- a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx
+++ b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx
@@ -88,6 +88,7 @@ export function HeaderTabs(props: HeaderTabsProps) {
{tabs.map((tab, index) => (
Read Docs
diff --git a/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx b/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx
index 9975db6435..9400ca3205 100644
--- a/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx
+++ b/plugins/techdocs/src/home/components/TechDocsCustomHome.tsx
@@ -108,7 +108,7 @@ const CustomPanel = ({
) : null}
>
);
@@ -182,7 +182,7 @@ export const TechDocsCustomHome = ({
label,
}))}
/>
-
+
{currentTabConfig.panels.map((config, index) => (
{
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 ;
+ }
+
return (
{
return (
<>
-
+