diff --git a/e2e/e2e.html b/e2e/e2e.html
new file mode 100644
index 00000000..3cf33b62
--- /dev/null
+++ b/e2e/e2e.html
@@ -0,0 +1,6 @@
+
+
+
+
+
+;
diff --git a/e2e/index.html b/e2e/index.html
new file mode 100644
index 00000000..3cf33b62
--- /dev/null
+++ b/e2e/index.html
@@ -0,0 +1,6 @@
+
+
+
+
+
+;
diff --git a/e2e/integration/misc.e2e.ts b/e2e/integration/misc.e2e.ts
new file mode 100644
index 00000000..5a3d1747
--- /dev/null
+++ b/e2e/integration/misc.e2e.ts
@@ -0,0 +1,64 @@
+// tslint:disable:no-implicit-dependencies
+import * as yaml from 'yaml-js';
+
+async function loadSpec(url: string): Promise {
+ const spec = await (await fetch(url)).text();
+ return yaml.load(spec);
+}
+
+function initReDoc(win, spec, options = {}) {
+ (win as any).Redoc.init(spec, options, win.document.getElementById('redoc'));
+}
+
+describe('Servers', () => {
+ beforeEach(() => {
+ cy.visit('e2e/');
+ });
+
+ it('should have valid server', () => {
+ cy.window().then(async win => {
+ const spec = await loadSpec('/demo/openapi.yaml');
+ initReDoc(win, spec, {});
+
+ // TODO add cy-data attributes
+ cy.get('[data-section-id="operation/addPet"]').should(
+ 'contain',
+ 'http://petstore.swagger.io/v2/pet',
+ );
+
+ cy.get('[data-section-id="operation/addPet"]').should(
+ 'contain',
+ 'http://petstore.swagger.io/sandbox/pet',
+ );
+ });
+ });
+
+ it('should have valid server for when servers not provided', () => {
+ cy.window().then(async win => {
+ const spec = await loadSpec('/demo/openapi.yaml');
+ delete spec.servers;
+ initReDoc(win, spec, {});
+
+ // TODO add cy-data attributes
+ cy.get('[data-section-id="operation/addPet"]').should(
+ 'contain',
+ 'http://localhost:' + win.location.port + '/e2e/pet',
+ );
+ });
+ });
+
+ it('should have valid server for when servers not provided at .html pages', () => {
+ cy.visit('e2e/e2e.html');
+ cy.window().then(async win => {
+ const spec = await loadSpec('/demo/openapi.yaml');
+ delete spec.servers;
+ initReDoc(win, spec, {});
+
+ // TODO add cy-data attributes
+ cy.get('[data-section-id="operation/addPet"]').should(
+ 'contain',
+ 'http://localhost:' + win.location.port + '/e2e/pet',
+ );
+ });
+ });
+});
diff --git a/src/components/Endpoint/Endpoint.tsx b/src/components/Endpoint/Endpoint.tsx
index bc7863d4..00d7bda0 100644
--- a/src/components/Endpoint/Endpoint.tsx
+++ b/src/components/Endpoint/Endpoint.tsx
@@ -5,7 +5,7 @@ import { Markdown } from '../Markdown/Markdown';
import { OptionsContext } from '../OptionsProvider';
import { SelectOnClick } from '../SelectOnClick/SelectOnClick';
-import {getBasePath, removeQueryString} from '../../utils';
+import { getBasePath } from '../../utils';
import {
EndpointInfo,
HttpVerb,
@@ -68,7 +68,7 @@ export class Endpoint extends React.Component {
{hideHostname || options.hideHostname
? getBasePath(server.url)
- : removeQueryString(server.url)}
+ : server.url}
{operation.path}
diff --git a/src/utils/openapi.ts b/src/utils/openapi.ts
index a500d313..d12ab9e2 100644
--- a/src/utils/openapi.ts
+++ b/src/utils/openapi.ts
@@ -11,7 +11,7 @@ import {
Referenced,
} from '../types';
import { IS_BROWSER } from './dom';
-import { isNumeric, resolveUrl } from './helpers';
+import { isNumeric, removeQueryString, resolveUrl, stripTrailingSlash } from './helpers';
function isWildcardStatusCode(statusCode: string | number): statusCode is string {
return typeof statusCode === 'string' && /\dxx/i.test(statusCode);
@@ -367,13 +367,20 @@ export function normalizeServers(
specUrl: string | undefined,
servers: OpenAPIServer[],
): OpenAPIServer[] {
- const baseUrl =
- specUrl === undefined ? (IS_BROWSER ? window.location.href : '') : dirname(specUrl);
+ const getHref = () => {
+ if (!IS_BROWSER) {
+ return '';
+ }
+ const href = window.location.href;
+ return href.endsWith('.html') ? dirname(href) : href;
+ };
+
+ const baseUrl = specUrl === undefined ? removeQueryString(getHref()) : dirname(specUrl);
if (servers.length === 0) {
return [
{
- url: baseUrl,
+ url: stripTrailingSlash(baseUrl),
},
];
}