@@ -14,73 +14,75 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { setupRequestMockHandlers } from '@backstage/test-utils';
|
||||
import { getManifestByReleaseLine, getManifestByVersion } from './manifest';
|
||||
import { setupServer } from 'msw/node';
|
||||
import { rest } from 'msw';
|
||||
import { setupRequestMockHandlers } from '@backstage/test-utils';
|
||||
import { getManifestByReleaseLine, getManifestByVersion } from './manifest';
|
||||
|
||||
describe('getManifestByVersion', () => {
|
||||
describe('Release Manifests', () => {
|
||||
const worker = setupServer();
|
||||
setupRequestMockHandlers(worker);
|
||||
|
||||
it('should return a list of packages in a release', async () => {
|
||||
worker.use(
|
||||
rest.get('*/v1/releases/0.0.0/manifest.json', (_, res, ctx) =>
|
||||
res(
|
||||
ctx.status(200),
|
||||
ctx.json({
|
||||
packages: [{ name: '@backstage/core', version: '1.2.3' }],
|
||||
}),
|
||||
describe('getManifestByVersion', () => {
|
||||
it('should return a list of packages in a release', async () => {
|
||||
worker.use(
|
||||
rest.get('*/v1/releases/0.0.0/manifest.json', (_, res, ctx) =>
|
||||
res(
|
||||
ctx.status(200),
|
||||
ctx.json({
|
||||
packages: [{ name: '@backstage/core', version: '1.2.3' }],
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
rest.get('*/v1/releases/999.0.1/manifest.json', (_, res, ctx) =>
|
||||
res(ctx.status(404), ctx.json({})),
|
||||
),
|
||||
);
|
||||
rest.get('*/v1/releases/999.0.1/manifest.json', (_, res, ctx) =>
|
||||
res(ctx.status(404), ctx.json({})),
|
||||
),
|
||||
);
|
||||
|
||||
const pkgs = await getManifestByVersion({ version: '0.0.0' });
|
||||
expect(pkgs.packages).toEqual([
|
||||
{
|
||||
name: '@backstage/core',
|
||||
version: '1.2.3',
|
||||
},
|
||||
]);
|
||||
const pkgs = await getManifestByVersion({ version: '0.0.0' });
|
||||
expect(pkgs.packages).toEqual([
|
||||
{
|
||||
name: '@backstage/core',
|
||||
version: '1.2.3',
|
||||
},
|
||||
]);
|
||||
|
||||
await expect(getManifestByVersion({ version: '999.0.1' })).rejects.toThrow(
|
||||
'No release found for 999.0.1 version',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getManifestByReleaseLine', () => {
|
||||
const worker = setupServer();
|
||||
setupRequestMockHandlers(worker);
|
||||
|
||||
it('should return a list of packages in a release', async () => {
|
||||
worker.use(
|
||||
rest.get('*/v1/tags/main/manifest.json', (_, res, ctx) =>
|
||||
res(
|
||||
ctx.status(200),
|
||||
ctx.json({
|
||||
packages: [{ name: '@backstage/core', version: '1.2.3' }],
|
||||
}),
|
||||
),
|
||||
),
|
||||
rest.get('*/v1/tags/foo/manifest.json', (_, res, ctx) =>
|
||||
res(ctx.status(404), ctx.json({})),
|
||||
),
|
||||
);
|
||||
|
||||
const pkgs = await getManifestByReleaseLine({ releaseLine: 'main' });
|
||||
expect(pkgs.packages).toEqual([
|
||||
{
|
||||
name: '@backstage/core',
|
||||
version: '1.2.3',
|
||||
},
|
||||
]);
|
||||
|
||||
await expect(
|
||||
getManifestByReleaseLine({ releaseLine: 'foo' }),
|
||||
).rejects.toThrow("No 'foo' release line found");
|
||||
await expect(
|
||||
getManifestByVersion({ version: '999.0.1' }),
|
||||
).rejects.toThrow('No release found for 999.0.1 version');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getManifestByReleaseLine', () => {
|
||||
it('should return a list of packages in a release', async () => {
|
||||
worker.use(
|
||||
rest.get(
|
||||
'https://versions.backstage.io/v1/tags/main/manifest.json',
|
||||
(_, res, ctx) =>
|
||||
res(
|
||||
ctx.status(200),
|
||||
ctx.json({
|
||||
packages: [{ name: '@backstage/core', version: '1.2.3' }],
|
||||
}),
|
||||
),
|
||||
),
|
||||
rest.get(
|
||||
'https://versions.backstage.io/v1/tags/foo/manifest.json',
|
||||
(_, res, ctx) => res(ctx.status(404), ctx.json({})),
|
||||
),
|
||||
);
|
||||
|
||||
const pkgs = await getManifestByReleaseLine({ releaseLine: 'main' });
|
||||
expect(pkgs.packages).toEqual([
|
||||
{
|
||||
name: '@backstage/core',
|
||||
version: '1.2.3',
|
||||
},
|
||||
]);
|
||||
|
||||
await expect(
|
||||
getManifestByReleaseLine({ releaseLine: 'foo' }),
|
||||
).rejects.toThrow("No 'foo' release line found");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -74,144 +74,145 @@ const expectedEntities: Entity[] = [
|
||||
},
|
||||
];
|
||||
|
||||
describe('DefaultTechDocsCollator with legacyPathCasing configuration', () => {
|
||||
let mockDiscoveryApi: jest.Mocked<PluginEndpointDiscovery>;
|
||||
let mockTokenManager: jest.Mocked<TokenManager>;
|
||||
let collator: DefaultTechDocsCollator;
|
||||
|
||||
describe('TechDocs Collator', () => {
|
||||
const worker = setupServer();
|
||||
setupRequestMockHandlers(worker);
|
||||
beforeEach(() => {
|
||||
mockDiscoveryApi = {
|
||||
getBaseUrl: jest.fn().mockResolvedValue('http://test-backend'),
|
||||
getExternalBaseUrl: jest.fn(),
|
||||
};
|
||||
mockTokenManager = {
|
||||
getToken: jest.fn().mockResolvedValue({ token: '' }),
|
||||
authenticate: jest.fn(),
|
||||
};
|
||||
const mockConfig = new ConfigReader({
|
||||
techdocs: {
|
||||
legacyUseCaseSensitiveTripletPaths: true,
|
||||
},
|
||||
});
|
||||
collator = DefaultTechDocsCollator.fromConfig(mockConfig, {
|
||||
discovery: mockDiscoveryApi,
|
||||
tokenManager: mockTokenManager,
|
||||
logger,
|
||||
legacyPathCasing: true,
|
||||
});
|
||||
|
||||
worker.use(
|
||||
rest.get(
|
||||
'http://test-backend/static/docs/default/Component/test-entity-with-docs/search/search_index.json',
|
||||
(_, res, ctx) => res(ctx.status(200), ctx.json(mockSearchDocIndex)),
|
||||
),
|
||||
rest.get('http://test-backend/entities', (_, res, ctx) =>
|
||||
res(ctx.status(200), ctx.json(expectedEntities)),
|
||||
),
|
||||
);
|
||||
});
|
||||
describe('DefaultTechDocsCollator with legacyPathCasing configuration', () => {
|
||||
let mockDiscoveryApi: jest.Mocked<PluginEndpointDiscovery>;
|
||||
let mockTokenManager: jest.Mocked<TokenManager>;
|
||||
let collator: DefaultTechDocsCollator;
|
||||
|
||||
it('fetches from the configured catalog and tech docs services', async () => {
|
||||
const documents = await collator.execute();
|
||||
expect(mockDiscoveryApi.getBaseUrl).toHaveBeenCalledWith('catalog');
|
||||
expect(mockDiscoveryApi.getBaseUrl).toHaveBeenCalledWith('techdocs');
|
||||
expect(documents).toHaveLength(mockSearchDocIndex.docs.length);
|
||||
});
|
||||
|
||||
it('should create documents for each tech docs search index', async () => {
|
||||
const documents = await collator.execute();
|
||||
const entity = expectedEntities[0];
|
||||
documents.forEach((document, idx) => {
|
||||
expect(document).toMatchObject({
|
||||
title: mockSearchDocIndex.docs[idx].title,
|
||||
location: `/docs/default/Component/${entity.metadata.name}/${mockSearchDocIndex.docs[idx].location}`,
|
||||
text: mockSearchDocIndex.docs[idx].text,
|
||||
namespace: 'default',
|
||||
entityTitle: entity!.metadata.title,
|
||||
componentType: entity!.spec!.type,
|
||||
lifecycle: entity!.spec!.lifecycle,
|
||||
owner: '',
|
||||
kind: entity.kind,
|
||||
name: entity.metadata.name,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('DefaultTechDocsCollator', () => {
|
||||
let mockDiscoveryApi: jest.Mocked<PluginEndpointDiscovery>;
|
||||
let mockTokenManager: jest.Mocked<TokenManager>;
|
||||
let collator: DefaultTechDocsCollator;
|
||||
|
||||
const worker = setupServer();
|
||||
setupRequestMockHandlers(worker);
|
||||
beforeEach(() => {
|
||||
mockDiscoveryApi = {
|
||||
getBaseUrl: jest.fn().mockResolvedValue('http://test-backend'),
|
||||
getExternalBaseUrl: jest.fn(),
|
||||
};
|
||||
mockTokenManager = {
|
||||
getToken: jest.fn().mockResolvedValue({ token: '' }),
|
||||
authenticate: jest.fn(),
|
||||
};
|
||||
collator = DefaultTechDocsCollator.fromConfig(new ConfigReader({}), {
|
||||
discovery: mockDiscoveryApi,
|
||||
tokenManager: mockTokenManager,
|
||||
logger,
|
||||
});
|
||||
|
||||
worker.use(
|
||||
rest.get(
|
||||
'http://test-backend/static/docs/default/component/test-entity-with-docs/search/search_index.json',
|
||||
(_, res, ctx) => res(ctx.status(200), ctx.json(mockSearchDocIndex)),
|
||||
),
|
||||
rest.get('http://test-backend/entities', (_, res, ctx) =>
|
||||
res(ctx.status(200), ctx.json(expectedEntities)),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it('should create documents for each tech docs search index', async () => {
|
||||
const documents = await collator.execute();
|
||||
const entity = expectedEntities[0];
|
||||
documents.forEach((document, idx) => {
|
||||
expect(document).toMatchObject({
|
||||
title: mockSearchDocIndex.docs[idx].title,
|
||||
location: `/docs/default/component/${entity.metadata.name}/${mockSearchDocIndex.docs[idx].location}`,
|
||||
text: mockSearchDocIndex.docs[idx].text,
|
||||
namespace: 'default',
|
||||
entityTitle: entity!.metadata.title,
|
||||
componentType: entity!.spec!.type,
|
||||
lifecycle: entity!.spec!.lifecycle,
|
||||
owner: '',
|
||||
kind: entity.kind.toLocaleLowerCase('en-US'),
|
||||
name: entity.metadata.name.toLocaleLowerCase('en-US'),
|
||||
authorization: {
|
||||
resourceRef: `component:default/${entity.metadata.name}`,
|
||||
beforeEach(() => {
|
||||
mockDiscoveryApi = {
|
||||
getBaseUrl: jest.fn().mockResolvedValue('http://test-backend'),
|
||||
getExternalBaseUrl: jest.fn(),
|
||||
};
|
||||
mockTokenManager = {
|
||||
getToken: jest.fn().mockResolvedValue({ token: '' }),
|
||||
authenticate: jest.fn(),
|
||||
};
|
||||
const mockConfig = new ConfigReader({
|
||||
techdocs: {
|
||||
legacyUseCaseSensitiveTripletPaths: true,
|
||||
},
|
||||
});
|
||||
collator = DefaultTechDocsCollator.fromConfig(mockConfig, {
|
||||
discovery: mockDiscoveryApi,
|
||||
tokenManager: mockTokenManager,
|
||||
logger,
|
||||
legacyPathCasing: true,
|
||||
});
|
||||
|
||||
worker.use(
|
||||
rest.get(
|
||||
'http://test-backend/static/docs/default/Component/test-entity-with-docs/search/search_index.json',
|
||||
(_, res, ctx) => res(ctx.status(200), ctx.json(mockSearchDocIndex)),
|
||||
),
|
||||
rest.get('http://test-backend/entities', (_, res, ctx) =>
|
||||
res(ctx.status(200), ctx.json(expectedEntities)),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it('fetches from the configured catalog and tech docs services', async () => {
|
||||
const documents = await collator.execute();
|
||||
expect(mockDiscoveryApi.getBaseUrl).toHaveBeenCalledWith('catalog');
|
||||
expect(mockDiscoveryApi.getBaseUrl).toHaveBeenCalledWith('techdocs');
|
||||
expect(documents).toHaveLength(mockSearchDocIndex.docs.length);
|
||||
});
|
||||
|
||||
it('should create documents for each tech docs search index', async () => {
|
||||
const documents = await collator.execute();
|
||||
const entity = expectedEntities[0];
|
||||
documents.forEach((document, idx) => {
|
||||
expect(document).toMatchObject({
|
||||
title: mockSearchDocIndex.docs[idx].title,
|
||||
location: `/docs/default/Component/${entity.metadata.name}/${mockSearchDocIndex.docs[idx].location}`,
|
||||
text: mockSearchDocIndex.docs[idx].text,
|
||||
namespace: 'default',
|
||||
entityTitle: entity!.metadata.title,
|
||||
componentType: entity!.spec!.type,
|
||||
lifecycle: entity!.spec!.lifecycle,
|
||||
owner: '',
|
||||
kind: entity.kind,
|
||||
name: entity.metadata.name,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('maps a returned entity with a custom locationTemplate', async () => {
|
||||
const mockConfig = new ConfigReader({
|
||||
techdocs: {
|
||||
legacyUseCaseSensitiveTripletPaths: true,
|
||||
},
|
||||
});
|
||||
// Provide an alternate location template.
|
||||
collator = DefaultTechDocsCollator.fromConfig(mockConfig, {
|
||||
discovery: mockDiscoveryApi,
|
||||
tokenManager: mockTokenManager,
|
||||
locationTemplate: '/software/:name',
|
||||
logger,
|
||||
describe('DefaultTechDocsCollator', () => {
|
||||
let mockDiscoveryApi: jest.Mocked<PluginEndpointDiscovery>;
|
||||
let mockTokenManager: jest.Mocked<TokenManager>;
|
||||
let collator: DefaultTechDocsCollator;
|
||||
|
||||
beforeEach(() => {
|
||||
mockDiscoveryApi = {
|
||||
getBaseUrl: jest.fn().mockResolvedValue('http://test-backend'),
|
||||
getExternalBaseUrl: jest.fn(),
|
||||
};
|
||||
mockTokenManager = {
|
||||
getToken: jest.fn().mockResolvedValue({ token: '' }),
|
||||
authenticate: jest.fn(),
|
||||
};
|
||||
collator = DefaultTechDocsCollator.fromConfig(new ConfigReader({}), {
|
||||
discovery: mockDiscoveryApi,
|
||||
tokenManager: mockTokenManager,
|
||||
logger,
|
||||
});
|
||||
|
||||
worker.use(
|
||||
rest.get(
|
||||
'http://test-backend/static/docs/default/component/test-entity-with-docs/search/search_index.json',
|
||||
(_, res, ctx) => res(ctx.status(200), ctx.json(mockSearchDocIndex)),
|
||||
),
|
||||
rest.get('http://test-backend/entities', (_, res, ctx) =>
|
||||
res(ctx.status(200), ctx.json(expectedEntities)),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
const documents = await collator.execute();
|
||||
expect(documents[0]).toMatchObject({
|
||||
location: '/software/test-entity-with-docs',
|
||||
it('should create documents for each tech docs search index', async () => {
|
||||
const documents = await collator.execute();
|
||||
const entity = expectedEntities[0];
|
||||
documents.forEach((document, idx) => {
|
||||
expect(document).toMatchObject({
|
||||
title: mockSearchDocIndex.docs[idx].title,
|
||||
location: `/docs/default/component/${entity.metadata.name}/${mockSearchDocIndex.docs[idx].location}`,
|
||||
text: mockSearchDocIndex.docs[idx].text,
|
||||
namespace: 'default',
|
||||
entityTitle: entity!.metadata.title,
|
||||
componentType: entity!.spec!.type,
|
||||
lifecycle: entity!.spec!.lifecycle,
|
||||
owner: '',
|
||||
kind: entity.kind.toLocaleLowerCase('en-US'),
|
||||
name: entity.metadata.name.toLocaleLowerCase('en-US'),
|
||||
authorization: {
|
||||
resourceRef: `component:default/${entity.metadata.name}`,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('maps a returned entity with a custom locationTemplate', async () => {
|
||||
const mockConfig = new ConfigReader({
|
||||
techdocs: {
|
||||
legacyUseCaseSensitiveTripletPaths: true,
|
||||
},
|
||||
});
|
||||
// Provide an alternate location template.
|
||||
collator = DefaultTechDocsCollator.fromConfig(mockConfig, {
|
||||
discovery: mockDiscoveryApi,
|
||||
tokenManager: mockTokenManager,
|
||||
locationTemplate: '/software/:name',
|
||||
logger,
|
||||
});
|
||||
|
||||
const documents = await collator.execute();
|
||||
expect(documents[0]).toMatchObject({
|
||||
location: '/software/test-entity-with-docs',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4196,6 +4196,18 @@
|
||||
outvariant "^1.2.1"
|
||||
strict-event-emitter "^0.2.0"
|
||||
|
||||
"@mswjs/interceptors@^0.16.3":
|
||||
version "0.16.4"
|
||||
resolved "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.16.4.tgz#fa41de240dd094e6ad19e3a6829651589551d159"
|
||||
integrity sha512-McPKUFlZNS/wo+OAor15k0fv2skK+EdWl9CEcdxAqsN4vKajlxCxDU4B5W/pn1y0TJPSAOmxR6LYFe/8esePrg==
|
||||
dependencies:
|
||||
"@open-draft/until" "^1.0.3"
|
||||
"@xmldom/xmldom" "^0.7.5"
|
||||
debug "^4.3.3"
|
||||
headers-polyfill "^3.0.4"
|
||||
outvariant "^1.2.1"
|
||||
strict-event-emitter "^0.2.4"
|
||||
|
||||
"@n1ru4l/graphql-live-query@^0.9.0":
|
||||
version "0.9.0"
|
||||
resolved "https://registry.npmjs.org/@n1ru4l/graphql-live-query/-/graphql-live-query-0.9.0.tgz#defaebdd31f625bee49e6745934f36312532b2bc"
|
||||
@@ -18159,13 +18171,13 @@ msw@^0.39.2:
|
||||
type-fest "^1.2.2"
|
||||
yargs "^17.3.1"
|
||||
|
||||
msw@^0.41.0:
|
||||
version "0.41.1"
|
||||
resolved "https://registry.npmjs.org/msw/-/msw-0.41.1.tgz#215f835d5c2b1f4a8aca2e92fa7608b0086b6891"
|
||||
integrity sha512-BNz8u1ORjyAXGaFEJ8mDhJr3nVaACSP4WR7V5XU8I2BnkTuAx93+gR13ovtH1gT66TO8rntOSSfRKZkWpSVufg==
|
||||
msw@^0.42.0:
|
||||
version "0.42.0"
|
||||
resolved "https://registry.npmjs.org/msw/-/msw-0.42.0.tgz#2286aefad82808888914e2bc5e40666e82b2824b"
|
||||
integrity sha512-vB9rzgiGHoQGfkKpp3QZHxobzfuuQOJk+0bff0wtbK8k3P3CaUSt8bCwvExours682AY4mUfTjIkCsxy0JoS3w==
|
||||
dependencies:
|
||||
"@mswjs/cookies" "^0.2.0"
|
||||
"@mswjs/interceptors" "^0.15.1"
|
||||
"@mswjs/interceptors" "^0.16.3"
|
||||
"@open-draft/until" "^1.0.3"
|
||||
"@types/cookie" "^0.4.1"
|
||||
"@types/js-levenshtein" "^1.1.1"
|
||||
@@ -18178,6 +18190,7 @@ msw@^0.41.0:
|
||||
is-node-process "^1.0.1"
|
||||
js-levenshtein "^1.1.6"
|
||||
node-fetch "^2.6.7"
|
||||
outvariant "^1.3.0"
|
||||
path-to-regexp "^6.2.0"
|
||||
statuses "^2.0.0"
|
||||
strict-event-emitter "^0.2.0"
|
||||
@@ -19086,7 +19099,7 @@ outdent@^0.5.0:
|
||||
resolved "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz#9e10982fdc41492bb473ad13840d22f9655be2ff"
|
||||
integrity sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==
|
||||
|
||||
outvariant@^1.2.1:
|
||||
outvariant@^1.2.1, outvariant@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmjs.org/outvariant/-/outvariant-1.3.0.tgz#c39723b1d2cba729c930b74bf962317a81b9b1c9"
|
||||
integrity sha512-yeWM9k6UPfG/nzxdaPlJkB2p08hCg4xP6Lx99F+vP8YF7xyZVfTmJjrrNalkmzudD4WFvNLVudQikqUmF8zhVQ==
|
||||
@@ -23176,6 +23189,13 @@ strict-event-emitter@^0.2.0:
|
||||
dependencies:
|
||||
events "^3.3.0"
|
||||
|
||||
strict-event-emitter@^0.2.4:
|
||||
version "0.2.4"
|
||||
resolved "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.2.4.tgz#365714f0c95f059db31064ca745d5b33e5b30f6e"
|
||||
integrity sha512-xIqTLS5azUH1djSUsLH9DbP6UnM/nI18vu8d43JigCQEoVsnY+mrlE+qv6kYqs6/1OkMnMIiL6ffedQSZStuoQ==
|
||||
dependencies:
|
||||
events "^3.3.0"
|
||||
|
||||
strict-uri-encode@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
|
||||
|
||||
Reference in New Issue
Block a user