Skip to content

Commit 9a38cb7

Browse files
authored
chore(e2e): clean-up and re-enable genai tests for web (#7555)
* chore(atlas-service): resolve config in runtime to make sure that env overrides are applied * chore(generative-ai): use atlasMetadata as a way to detect which url preset to use * chore(assistant): dynamically resolve service url * chore(e2e, web): remove override inlining from the build; make atlas service mock handle CORS properly; re-enable disabled genai tests * chore(e2e): restore lost screenshots
1 parent 0a5fede commit 9a38cb7

File tree

16 files changed

+197
-234
lines changed

16 files changed

+197
-234
lines changed

packages/atlas-service/src/atlas-service.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ function getAtlasService(
2929
const atlasService = new AtlasService(
3030
authService,
3131
preferences,
32-
createNoopLogger()
32+
createNoopLogger(),
33+
undefined,
34+
ATLAS_CONFIG
3335
);
34-
atlasService['config'] = ATLAS_CONFIG;
3536
return atlasService;
3637
}
3738

packages/atlas-service/src/atlas-service.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,17 @@ function getAutomationAgentClusterId(
5353
}
5454

5555
export class AtlasService {
56-
private config: AtlasServiceConfig;
5756
constructor(
5857
private readonly authService: AtlasAuthService,
5958
private readonly preferences: PreferencesAccess,
6059
private readonly logger: Logger,
61-
private readonly options?: AtlasServiceOptions
62-
) {
63-
this.config = getAtlasConfig(preferences);
60+
private readonly options?: AtlasServiceOptions,
61+
private readonly defaultConfigOverride?: AtlasServiceConfig
62+
) {}
63+
// Config value is dynamic to make sure that process.env overrides are taken
64+
// into account in runtime
65+
get config(): AtlasServiceConfig {
66+
return this.defaultConfigOverride ?? getAtlasConfig(this.preferences);
6467
}
6568
adminApiEndpoint(path?: string): string {
6669
return `${this.config.atlasApiBaseUrl}${normalizePath(path)}`;

packages/atlas-service/src/util.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ export function getAtlasConfig(
255255
const { atlasServiceBackendPreset } = preferences.getPreferences();
256256
const envConfig = {
257257
atlasApiBaseUrl: process.env.COMPASS_ATLAS_SERVICE_UNAUTH_BASE_URL_OVERRIDE,
258+
cloudBaseUrl: process.env.COMPASS_CLOUD_BASE_URL_OVERRIDE,
258259
atlasLogin: {
259260
clientId: process.env.COMPASS_CLIENT_ID_OVERRIDE,
260261
issuer: process.env.COMPASS_OIDC_ISSUER_OVERRIDE,

packages/compass-assistant/src/compass-assistant-provider.spec.tsx

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { CompassAssistantDrawer } from './compass-assistant-drawer';
2828
import { createBrokenTransport, createMockChat } from '../test/utils';
2929
import type { AtlasAiService } from '@mongodb-js/compass-generative-ai/provider';
3030
import type { TrackFunction } from '@mongodb-js/compass-telemetry';
31-
import { createLogger } from '@mongodb-js/compass-logging';
31+
import { createNoopLogger } from '@mongodb-js/compass-logging/provider';
3232

3333
function createMockProvider({
3434
mockAtlasService,
@@ -480,7 +480,7 @@ describe('CompassAssistantProvider', function () {
480480
.stub()
481481
.returns('https://localhost:3000'),
482482
} as unknown as AtlasService,
483-
logger: createLogger('COMPASS-ASSISTANT-TEST'),
483+
logger: createNoopLogger(),
484484
track: track as unknown as TrackFunction,
485485
});
486486
await renderOpenAssistantDrawer({
@@ -654,47 +654,42 @@ describe('CompassAssistantProvider', function () {
654654
});
655655
});
656656

657+
let sandbox: sinon.SinonSandbox;
658+
659+
beforeEach(function () {
660+
sandbox = sinon.createSandbox();
661+
});
662+
663+
afterEach(function () {
664+
if (sandbox) {
665+
sandbox.reset();
666+
}
667+
});
668+
657669
it('uses the Atlas Service assistantApiEndpoint', async function () {
658670
const mockAtlasService = {
659-
assistantApiEndpoint: sinon
671+
assistantApiEndpoint: sandbox
660672
.stub()
661673
.returns('https://example.com/assistant/api/v1'),
662674
};
663675

664-
const mockAtlasAiService = {
665-
ensureAiFeatureAccess: sinon.stub().callsFake(() => {
666-
return Promise.resolve();
667-
}),
668-
};
669-
670-
const mockAtlasAuthService = {};
671-
672-
const MockedProvider = CompassAssistantProvider.withMockServices({
676+
const chat = createDefaultChat({
677+
originForPrompt: 'foo',
678+
appNameForPrompt: 'bar',
673679
atlasService: mockAtlasService as unknown as AtlasService,
674-
atlasAiService: mockAtlasAiService as unknown as AtlasAiService,
675-
atlasAuthService: mockAtlasAuthService as unknown as AtlasAuthService,
680+
logger: createNoopLogger(),
681+
track: () => undefined,
676682
});
677683

678-
render(
679-
<DrawerContentProvider>
680-
<DrawerAnchor />
681-
<MockedProvider
682-
originForPrompt="mongodb-compass"
683-
appNameForPrompt="MongoDB Compass"
684-
/>
685-
</DrawerContentProvider>,
686-
{
687-
preferences: {
688-
enableAIAssistant: true,
689-
enableGenAIFeatures: true,
690-
enableGenAIFeaturesAtlasOrg: true,
691-
cloudFeatureRolloutAccess: { GEN_AI_COMPASS: true },
692-
},
693-
}
694-
);
684+
const fetchStub = sandbox
685+
.stub(globalThis, 'fetch')
686+
.resolves({ ok: true, headers: [] } as any);
695687

696-
await waitFor(() => {
697-
expect(mockAtlasService.assistantApiEndpoint.calledOnce).to.be.true;
698-
});
688+
await chat.sendMessage({ text: 'hello' });
689+
690+
expect(mockAtlasService.assistantApiEndpoint.calledOnce).to.be.true;
691+
expect(fetchStub.lastCall.args[0]).to.eq(
692+
'https://example.com/assistant/api/v1/responses'
693+
);
699694
});
700695
});

packages/compass-assistant/src/compass-assistant-provider.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ export function createDefaultChat({
334334
transport: Chat<AssistantMessage>['transport'];
335335
};
336336
}): Chat<AssistantMessage> {
337+
const initialBaseUrl = 'http://PLACEHOLDER_BASE_URL_TO_BE_REPLACED.invalid';
337338
return new Chat({
338339
transport:
339340
options?.transport ??
@@ -343,8 +344,21 @@ export function createDefaultChat({
343344
target: appNameForPrompt,
344345
}),
345346
model: createOpenAI({
346-
baseURL: atlasService.assistantApiEndpoint(),
347+
baseURL: initialBaseUrl,
347348
apiKey: '',
349+
fetch(url, init) {
350+
return globalThis.fetch(
351+
// The `baseUrl` can be dynamically changed, but `createOpenAI`
352+
// constructor doesn't allow us to change it after initial call.
353+
// Instead we're going to update it every time the fetch call
354+
// happens
355+
String(url).replace(
356+
initialBaseUrl,
357+
atlasService.assistantApiEndpoint()
358+
),
359+
init
360+
);
361+
},
348362
}).responses('mongodb-chat-latest'),
349363
}),
350364
onError: (err: Error) => {

packages/compass-e2e-tests/helpers/assistant-service.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ function sendStreamingResponse(res: http.ServerResponse, content: string) {
140140
sendChunk();
141141
}
142142

143-
export const MOCK_ASSISTANT_SERVER_PORT = 27097;
144143
export async function startMockAssistantServer(
145144
{
146145
response: _response,
@@ -222,7 +221,7 @@ export async function startMockAssistantServer(
222221
return sendStreamingResponse(res, response.body);
223222
});
224223
})
225-
.listen(MOCK_ASSISTANT_SERVER_PORT);
224+
.listen(0);
226225
await once(server, 'listening');
227226

228227
// address() returns either a string or AddressInfo.

packages/compass-e2e-tests/helpers/compass-web-sandbox.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
} from './test-runner-paths';
1212
import type { ConnectionInfo } from '@mongodb-js/connection-info';
1313
import ConnectionString from 'mongodb-connection-string-url';
14-
import { MOCK_ASSISTANT_SERVER_PORT } from './assistant-service';
1514

1615
const debug = Debug('compass-e2e-tests:compass-web-sandbox');
1716

@@ -22,9 +21,6 @@ const debug = Debug('compass-e2e-tests:compass-web-sandbox');
2221
process.env.OPEN_BROWSER = 'false'; // tell webpack dev server not to open the default browser
2322
process.env.DISABLE_DEVSERVER_OVERLAY = 'true';
2423
process.env.APP_ENV = 'webdriverio';
25-
// Set the assistant base URL override for tests so we can mock the assistant server
26-
process.env.COMPASS_ASSISTANT_BASE_URL_OVERRIDE = `http://localhost:${MOCK_ASSISTANT_SERVER_PORT}`;
27-
process.env.COMPASS_OVERRIDE_ENABLE_AI_FEATURES = 'true';
2824

2925
const wait = (ms: number) => {
3026
return new Promise((resolve) => {

packages/compass-e2e-tests/helpers/atlas-service.ts renamed to packages/compass-e2e-tests/helpers/mock-atlas-service.ts

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -61,33 +61,62 @@ export async function startMockAtlasServiceServer(
6161
let response = _response;
6262
const server = http
6363
.createServer((req, res) => {
64-
if (req.method === 'GET') {
65-
requests.push({
66-
req,
67-
content: null,
68-
});
69-
return aiFeatureEnableResponse(req, res);
64+
res.setHeader('Access-Control-Allow-Origin', req.headers.origin ?? '*');
65+
res.setHeader('Access-Control-Allow-Credentials', 'true');
66+
res.setHeader(
67+
'Access-Control-Allow-Headers',
68+
req.headers['access-control-request-headers'] ?? '*'
69+
);
70+
71+
if (req.method === 'OPTIONS') {
72+
res.statusCode = 200;
73+
res.end();
74+
return;
75+
}
76+
77+
if (req.url?.startsWith('/settings/optInDataExplorerGenAIFeatures')) {
78+
res.statusCode = 200;
79+
res.end();
80+
return;
7081
}
7182

72-
let body = '';
73-
req
74-
.setEncoding('utf8')
75-
.on('data', (chunk) => {
76-
body += chunk;
77-
})
78-
.on('end', () => {
79-
const jsonObject = JSON.parse(body);
83+
if (req.url?.startsWith('/unauth/ai/api/v1/mql-query')) {
84+
if (req.method === 'GET') {
8085
requests.push({
8186
req,
82-
content: jsonObject,
87+
content: null,
8388
});
89+
return aiFeatureEnableResponse(req, res);
90+
}
91+
92+
let body = '';
93+
94+
req
95+
.setEncoding('utf8')
96+
.on('data', (chunk) => {
97+
body += chunk;
98+
})
99+
.on('end', () => {
100+
const jsonObject = JSON.parse(body);
101+
requests.push({
102+
req,
103+
content: jsonObject,
104+
});
105+
106+
res.setHeader('Content-Type', 'application/json');
107+
if (response.status !== 200) {
108+
res.writeHead(response.status);
109+
}
110+
return res.end(JSON.stringify(response.body));
111+
});
112+
113+
return;
114+
}
84115

85-
res.setHeader('Content-Type', 'application/json');
86-
if (response.status !== 200) {
87-
res.writeHead(response.status);
88-
}
89-
return res.end(JSON.stringify(response.body));
90-
});
116+
res.statusCode = 404;
117+
res.statusMessage =
118+
'Route not found in the mock Atlas backend. Did you forget to add a mock route support?';
119+
res.end();
91120
})
92121
.listen(0);
93122
await once(server, 'listening');

0 commit comments

Comments
 (0)