From 06f6a4f0f14de66fe5372e5f9d773e9076ee3e96 Mon Sep 17 00:00:00 2001 From: Scott Guymer Date: Fri, 2 Dec 2022 16:48:22 +0100 Subject: [PATCH 1/4] fix: allow overriding of stackoverflow configuration Make it possible to override the config when instantiating for more flexibility. Signed-off-by: Scott Guymer --- .changeset/olive-eyes-sing.md | 5 +++++ .../src/search/StackOverflowQuestionsCollatorFactory.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/olive-eyes-sing.md diff --git a/.changeset/olive-eyes-sing.md b/.changeset/olive-eyes-sing.md new file mode 100644 index 0000000000..d0ae1dc08f --- /dev/null +++ b/.changeset/olive-eyes-sing.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-stack-overflow-backend': minor +--- + +Enable configuration override for StackOverflow backend plugin when instantiating the search indexer. This makes it possible to set different configuration for frontend and backend of the plugin. diff --git a/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts b/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts index ebbad99d0a..807d6637c1 100644 --- a/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts +++ b/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.ts @@ -95,11 +95,11 @@ export class StackOverflowQuestionsCollatorFactory 'https://api.stackexchange.com/2.2'; const maxPage = options.maxPage || 100; return new StackOverflowQuestionsCollatorFactory({ - ...options, baseUrl, maxPage, apiKey, apiAccessToken, + ...options, }); } From 6151f8e07166a25e7940a303609ab11bdd91adcc Mon Sep 17 00:00:00 2001 From: Scott Guymer Date: Mon, 5 Dec 2022 09:19:49 +0100 Subject: [PATCH 2/4] Added some basic tests for stackoverflow backend plugin Signed-off-by: Scott Guymer --- plugins/stack-overflow-backend/package.json | 8 +- ...ckOverflowQuestionsCollatorFactory.test.ts | 151 ++++++++++++++++++ 2 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.test.ts diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index 5a58f54958..1750ddbc6c 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -32,13 +32,19 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/cli": "workspace:^", + "@backstage/backend-common": "workspace:^", "@backstage/config": "workspace:^", "@backstage/plugin-search-common": "workspace:^", "node-fetch": "^2.6.7", "qs": "^6.9.4", "winston": "^3.2.1" }, + "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "@backstage/plugin-search-backend-node": "workspace:^", + "msw": "^0.49.0" + }, "files": [ "dist", "config.d.ts" diff --git a/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.test.ts b/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.test.ts new file mode 100644 index 0000000000..9f2c316be4 --- /dev/null +++ b/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.test.ts @@ -0,0 +1,151 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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 { getVoidLogger } from '@backstage/backend-common'; +import { + StackOverflowQuestionsCollatorFactory, + StackOverflowQuestionsCollatorFactoryOptions, +} from './StackOverflowQuestionsCollatorFactory'; +import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; +import { TestPipeline } from '@backstage/plugin-search-backend-node'; +import { ConfigReader } from '@backstage/config'; +import { Readable } from 'stream'; +import { setupServer } from 'msw/node'; +import { rest } from 'msw'; + +const logger = getVoidLogger(); + +const mockQuestion = { + items: [ + { + tags: ['backstage'], + owner: { + display_name: 'The Riddler', + }, + answer_count: 1, + link: 'https://stack.overflow.local/questions/2911', + title: 'This is the first question', + }, + ], + has_more: false, +}; + +const mockOverrideQuestion = { + items: [ + { + tags: ['backstage'], + owner: { + display_name: 'The Riddler', + }, + answer_count: 1, + link: 'https://stack.overflow.local/questions/1', + title: 'This is the first question', + }, + { + tags: ['backstage'], + owner: { + display_name: 'The Riddler', + }, + answer_count: 1, + link: 'https://stack.overflow.local/questions/2', + title: 'this is another question', + }, + ], + has_more: false, +}; + +describe('StackOverflowQuestionsCollatorFactory', () => { + const config = new ConfigReader({ + stackoverflow: { + baseUrl: 'http://stack.overflow.local', + }, + }); + + const defaultOptions: StackOverflowQuestionsCollatorFactoryOptions = { + logger, + requestParams: { + tagged: ['developer-portal'], + pagesize: 100, + order: 'desc', + sort: 'activity', + }, + }; + + it('has expected type', () => { + const factory = StackOverflowQuestionsCollatorFactory.fromConfig( + config, + defaultOptions, + ); + expect(factory.type).toBe('stack-overflow'); + }); + + describe('getCollator', () => { + const worker = setupServer(); + setupRequestMockHandlers(worker); + + afterEach(async () => { + worker.resetHandlers(); + }); + + afterAll(async () => { + worker.close(); + }); + + it('returns a readable stream', async () => { + const factory = StackOverflowQuestionsCollatorFactory.fromConfig( + config, + defaultOptions, + ); + const collator = await factory.getCollator(); + expect(collator).toBeInstanceOf(Readable); + }); + + it('fetches from the configured endpoint', async () => { + worker.use( + rest.get('http://stack.overflow.local/questions', (_, res, ctx) => + res(ctx.status(200), ctx.json(mockQuestion)), + ), + ); + const factory = StackOverflowQuestionsCollatorFactory.fromConfig( + config, + defaultOptions, + ); + const collator = await factory.getCollator(); + const pipeline = TestPipeline.fromCollator(collator); + const { documents } = await pipeline.execute(); + + expect(documents).toHaveLength(mockQuestion.items.length); + }); + + it('fetches from the overridden endpoint', async () => { + worker.use( + rest.get('http://stack.overflow.override/questions', (_, res, ctx) => + res(ctx.status(200), ctx.json(mockOverrideQuestion)), + ), + ); + const factory = StackOverflowQuestionsCollatorFactory.fromConfig(config, { + logger, + baseUrl: 'http://stack.overflow.override', + requestParams: defaultOptions.requestParams, + }); + const collator = await factory.getCollator(); + + const pipeline = TestPipeline.fromCollator(collator); + const { documents } = await pipeline.execute(); + + expect(documents).toHaveLength(mockOverrideQuestion.items.length); + }); + }); +}); From 9e4725f8f4736dbccccef47a8ed640abc383e5c0 Mon Sep 17 00:00:00 2001 From: Scott Guymer Date: Mon, 5 Dec 2022 09:38:20 +0100 Subject: [PATCH 3/4] Updated yarn.lock Signed-off-by: Scott Guymer --- yarn.lock | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/yarn.lock b/yarn.lock index 4af9e1862a..9b8f80db7e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7845,9 +7845,13 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-stack-overflow-backend@workspace:plugins/stack-overflow-backend" dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" + "@backstage/plugin-search-backend-node": "workspace:^" "@backstage/plugin-search-common": "workspace:^" + msw: ^0.49.0 node-fetch: ^2.6.7 qs: ^6.9.4 winston: ^3.2.1 From 2f52b1274009c3542f578d290a894885f5d1b75e Mon Sep 17 00:00:00 2001 From: Scott Guymer Date: Wed, 7 Dec 2022 17:13:11 +0100 Subject: [PATCH 4/4] Remove cleanup calls as they are handled in the setup of msw Signed-off-by: Scott Guymer --- .../search/StackOverflowQuestionsCollatorFactory.test.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.test.ts b/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.test.ts index 9f2c316be4..bdc5be125c 100644 --- a/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.test.ts +++ b/plugins/stack-overflow-backend/src/search/StackOverflowQuestionsCollatorFactory.test.ts @@ -95,14 +95,6 @@ describe('StackOverflowQuestionsCollatorFactory', () => { const worker = setupServer(); setupRequestMockHandlers(worker); - afterEach(async () => { - worker.resetHandlers(); - }); - - afterAll(async () => { - worker.close(); - }); - it('returns a readable stream', async () => { const factory = StackOverflowQuestionsCollatorFactory.fromConfig( config,