From fdcaf5d93829f5a2f23fe756a9d1b22aa3563262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 23 May 2024 11:37:47 +0200 Subject: [PATCH] move to startTestBackend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- plugins/proxy-backend/package.json | 4 +- .../src/service/router.config.test.ts | 93 +++++++++---------- .../src/service/router.credentials.test.ts | 83 ++++++++--------- yarn.lock | 2 +- 4 files changed, 87 insertions(+), 95 deletions(-) diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 3d3ccfaa0d..af0d9d584e 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -65,6 +65,7 @@ "yup": "^1.0.0" }, "devDependencies": { + "@backstage/backend-app-api": "workspace:^", "@backstage/backend-defaults": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", @@ -74,8 +75,7 @@ "@types/uuid": "^9.0.0", "@types/yup": "^0.32.0", "msw": "^2.0.0", - "node-fetch": "^2.6.7", - "portfinder": "^1.0.32" + "node-fetch": "^2.6.7" }, "configSchema": "config.d.ts" } diff --git a/plugins/proxy-backend/src/service/router.config.test.ts b/plugins/proxy-backend/src/service/router.config.test.ts index c868092612..ba81553a4f 100644 --- a/plugins/proxy-backend/src/service/router.config.test.ts +++ b/plugins/proxy-backend/src/service/router.config.test.ts @@ -14,14 +14,13 @@ * limitations under the License. */ -import { createBackend } from '@backstage/backend-defaults'; import { coreServices, createServiceFactory, } from '@backstage/backend-plugin-api'; import { - mockServices, setupRequestMockHandlers, + startTestBackend, } from '@backstage/backend-test-utils'; import { ConfigSources, @@ -31,7 +30,6 @@ import { import { HttpResponse, http, passthrough } from 'msw'; import { setupServer } from 'msw/node'; import fetch from 'node-fetch'; -import portFinder from 'portfinder'; // this test is stored in its own file to work around the mocked // http-proxy-middleware module used in the main test file @@ -41,30 +39,12 @@ describe('createRouter reloadable configuration', () => { setupRequestMockHandlers(server); it('should be able to observe the config', async () => { - const host = 'localhost'; - const port = await portFinder.getPortPromise({ host }); - const baseUrl = `http://${host}:${port}`; - - server.use( - http.all(`${baseUrl}/*`, passthrough), - http.get('https://non-existing-example.com/*', req => - HttpResponse.json({ - url: req.request.url.toString(), - headers: req.request.headers, - }), - ), - ); - // Grab the subscriber function and use mutable config data to mock a config file change const mutableConfigSource = MutableConfigSource.create({ data: {} }); const config = await ConfigSources.toConfig( ConfigSources.merge([ StaticConfigSource.create({ data: { - backend: { - baseUrl, - listen: { host, port }, - }, proxy: { endpoints: { '/test': { @@ -79,38 +59,53 @@ describe('createRouter reloadable configuration', () => { ]), ); - const backend = createBackend(); - backend.add(import('../alpha')); - backend.add( - createServiceFactory({ - service: coreServices.rootConfig, - deps: {}, - factory: () => config, - }), - ); - backend.add(mockServices.rootLogger.factory()); - await backend.start(); - - await expect(fetch(`${baseUrl}/api/proxy/test`)).resolves.toMatchObject({ - status: 200, + const backend = await startTestBackend({ + features: [ + import('../alpha'), + createServiceFactory({ + service: coreServices.rootConfig, + deps: {}, + factory: () => config, + }), + ], }); - await expect( - fetch(`${baseUrl}/api/proxy/test2`), - ).resolves.not.toMatchObject({ status: 200 }); - mutableConfigSource.setData({ - proxy: { - endpoints: { - '/test2': { - target: 'https://non-existing-example.com', - credentials: 'dangerously-allow-unauthenticated', + try { + const baseUrl = `http://localhost:${backend.server.port()}`; + + server.use( + http.all(`${baseUrl}/*`, passthrough), + http.get('https://non-existing-example.com/*', req => + HttpResponse.json({ + url: req.request.url.toString(), + headers: req.request.headers, + }), + ), + ); + + await expect(fetch(`${baseUrl}/api/proxy/test`)).resolves.toMatchObject({ + status: 200, + }); + await expect( + fetch(`${baseUrl}/api/proxy/test2`), + ).resolves.not.toMatchObject({ status: 200 }); + + mutableConfigSource.setData({ + proxy: { + endpoints: { + '/test2': { + target: 'https://non-existing-example.com', + credentials: 'dangerously-allow-unauthenticated', + }, }, }, - }, - }); + }); - await expect(fetch(`${baseUrl}/api/proxy/test2`)).resolves.toMatchObject({ - status: 200, - }); + await expect(fetch(`${baseUrl}/api/proxy/test2`)).resolves.toMatchObject({ + status: 200, + }); + } finally { + await backend.stop(); + } }); }); diff --git a/plugins/proxy-backend/src/service/router.credentials.test.ts b/plugins/proxy-backend/src/service/router.credentials.test.ts index 53d0f157f3..54c865ba11 100644 --- a/plugins/proxy-backend/src/service/router.credentials.test.ts +++ b/plugins/proxy-backend/src/service/router.credentials.test.ts @@ -14,17 +14,20 @@ * limitations under the License. */ -import { createBackend } from '@backstage/backend-defaults'; +import { + authServiceFactory, + httpAuthServiceFactory, +} from '@backstage/backend-app-api'; import { mockServices, setupRequestMockHandlers, + startTestBackend, } from '@backstage/backend-test-utils'; import { ResponseError } from '@backstage/errors'; import { JsonObject } from '@backstage/types'; -import { http, HttpResponse, passthrough } from 'msw'; +import { HttpResponse, http, passthrough } from 'msw'; import { setupServer } from 'msw/node'; import fetch from 'node-fetch'; -import portFinder from 'portfinder'; // this test is stored in its own file to work around the mocked // http-proxy-middleware module used in the main test file @@ -34,14 +37,8 @@ describe('credentials', () => { setupRequestMockHandlers(worker); it('handles all valid credentials settings', async () => { - const host = 'localhost'; - const port = await portFinder.getPortPromise({ host }); - const baseUrl = `http://${host}:${port}`; - const config = { backend: { - baseUrl, - listen: { host, port }, auth: { externalAccess: [ { @@ -81,42 +78,42 @@ describe('credentials', () => { }, }; - worker.use( - http.all(`${baseUrl}/*`, passthrough), - http.get('http://target.com/*', req => { - const auth = req.request.headers.get('authorization'); - return HttpResponse.json({ - payload: { forwardedAuthorization: auth ?? false }, - }); - }), - ); - - async function call(options: { - endpoint: string; - authorization: string | false; - }): Promise { - const { endpoint, authorization } = options; - return fetch(`${baseUrl}/api/proxy/${endpoint}/just-some-path`, { - headers: authorization ? { Authorization: authorization } : {}, - }).then(async res => { - if (!res.ok) { - throw await ResponseError.fromResponse(res); - } - return res.json(); - }); - } - - // Create an actual backend instead of a test backend, because we want to - // use the real HTTP server that provides the protection middleware etc. A - // bit harder to test, but at least we can use static external access tokens - // for it. - const backend = createBackend(); - backend.add(import('../alpha')); - backend.add(mockServices.rootConfig.factory({ data: config })); - backend.add(mockServices.rootLogger.factory()); - await backend.start(); + const backend = await startTestBackend({ + features: [ + import('../alpha'), + mockServices.rootConfig.factory({ data: config }), + authServiceFactory(), + httpAuthServiceFactory(), + ], + }); try { + const baseUrl = `http://localhost:${backend.server.port()}`; + worker.use( + http.all(`${baseUrl}/*`, passthrough), + http.get('http://target.com/*', req => { + const auth = req.request.headers.get('authorization'); + return HttpResponse.json({ + payload: { forwardedAuthorization: auth ?? false }, + }); + }), + ); + + const call = async (options: { + endpoint: string; + authorization: string | false; + }): Promise => { + const { endpoint, authorization } = options; + return fetch(`${baseUrl}/api/proxy/${endpoint}/just-some-path`, { + headers: authorization ? { Authorization: authorization } : {}, + }).then(async res => { + if (!res.ok) { + throw await ResponseError.fromResponse(res); + } + return res.json(); + }); + }; + // simple credentials config await expect( call({ endpoint: 'simple', authorization: false }), diff --git a/yarn.lock b/yarn.lock index 3288ed9a2e..329a17a855 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6453,6 +6453,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-proxy-backend@workspace:plugins/proxy-backend" dependencies: + "@backstage/backend-app-api": "workspace:^" "@backstage/backend-common": "workspace:^" "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" @@ -6472,7 +6473,6 @@ __metadata: morgan: ^1.10.0 msw: ^2.0.0 node-fetch: ^2.6.7 - portfinder: ^1.0.32 uuid: ^9.0.0 winston: ^3.2.1 yaml: ^2.0.0