Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue #4494 Allow endpoint handlers configurations from inside a test #4952

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions test/source/mock/all-apis-mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import { mockSksEndpoints } from './sks/sks-endpoints';
import { mockCustomerUrlFesEndpoints } from './fes/customer-url-fes-endpoints';
import { mockSharedTenantFesEndpoints } from './fes/shared-tenant-fes-endpoints';

export type HandlersDefinition = Handlers<{ query: { [k: string]: string }; body?: unknown }, unknown>;
export type RequestType = { query: { [k: string]: string }; body?: unknown };
export type HandlersDefinition = Handlers<RequestType, unknown>;

export const startAllApisMock = async (logger: (line: string) => void) => {
class LoggedApi<REQ, RES> extends Api<REQ, RES> {
Expand All @@ -25,7 +26,7 @@ export const startAllApisMock = async (logger: (line: string) => void) => {
}
};
}
const api = new LoggedApi<{ query: { [k: string]: string }; body?: unknown }, unknown>('google-mock', {
const api = new LoggedApi<RequestType, unknown>('google-mock', {
...mockGoogleEndpoints,
...mockBackendEndpoints,
...mockAttesterEndpoints,
Expand Down
4 changes: 4 additions & 0 deletions test/source/mock/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ export class Api<REQ, RES> {
});
}

public setHandlers = (handlers: Handlers<REQ, RES>) => {
this.handlers = handlers;
};

public listen = (host = '127.0.0.1', maxMb = 100): Promise<void> => {
return new Promise((resolve, reject) => {
try {
Expand Down
1 change: 1 addition & 0 deletions test/source/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ const startMockApiAndCopyBuild = async (t: AvaContext) => {

t.extensionDir = result.stdout;
t.urls = new TestUrls(await browserPool.getExtensionId(t), address.port);
t.mockApi = mockApi;
} else {
t.log('Failed to get mock build address');
}
Expand Down
15 changes: 14 additions & 1 deletion test/source/tests/compose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { InboxPageRecipe } from './page-recipe/inbox-page-recipe';
import { OauthPageRecipe } from './page-recipe/oauth-page-recipe';
import { PageRecipe } from './page-recipe/abstract-page-recipe';
import { SettingsPageRecipe } from './page-recipe/settings-page-recipe';
import { protonMailCompatKey, somePubkey } from './../mock/attester/attester-endpoints';
import { mockAttesterEndpoints, protonMailCompatKey, somePubkey } from './../mock/attester/attester-endpoints';
import { TestVariant } from './../util';
import { TestWithBrowser } from './../test';
import { expect } from 'chai';
Expand All @@ -24,6 +24,9 @@ import { MsgUtil } from '../core/crypto/pgp/msg-util';
import { Buf } from '../core/buf';
import { PubkeyInfoWithLastCheck } from '../core/crypto/key';
import { ElementHandle, Page } from 'puppeteer';
import { mockGoogleEndpoints } from '../mock/google/google-endpoints';
import { mockKeyManagerEndpoints } from '../mock/key-manager/key-manager-endpoints';
import { mockCustomerUrlFesEndpoints } from '../mock/fes/customer-url-fes-endpoints';

export const defineComposeTests = (testVariant: TestVariant, testWithBrowser: TestWithBrowser) => {
if (testVariant !== 'CONSUMER-LIVE-GMAIL') {
Expand Down Expand Up @@ -2545,6 +2548,16 @@ export const defineComposeTests = (testVariant: TestVariant, testWithBrowser: Te
test(
'user3@standardsubdomainfes.localhost:8001 - PWD encrypted message with FES web portal - pubkey recipient in bcc',
testWithBrowser(undefined, async (t, browser) => {
t.mockApi?.setHandlers({
...mockGoogleEndpoints,
// ...mockBackendEndpoints,
...mockAttesterEndpoints,
...mockKeyManagerEndpoints,
// ...mockWkdEndpoints,
// ...mockSksEndpoints,
...mockCustomerUrlFesEndpoints,
// ...mockSharedTenantFesEndpoints,
});
Comment on lines +2551 to +2560
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't mean this way, setting handlers.

I meant we would be setting configuration. Since now we have one MockApi per per test, we have an opportunity to configure mock api with different data (or expectations).

Like this:

    mockApi.fesConfig = { ... }; // particular client configuration for this test
    mockApi.ekmConfig = { returnKeys: [ekmKeySamples.e2eValidKey.prv] } // same
    mockApi.attesterConfig = { ... }; // configure Attester with particular public keys for this test 
    mockApi.googleConfig = {
      accounts: {
        'e2e.enterprise.test@flowcrypt.com': { // which account is allowed for Gmail login in this test
          messages: ['CC and BCC test'], // exported messages pre-loaded for this test, by subject
        }
      }
    }

notice it's receiving information on what to return (per service), not receiving the endpoints directly as done in the PR.

Have a look at any iOS mock tests, like these:
https://github.com/FlowCrypt/flowcrypt-ios/blob/master/appium/tests/specs/mock/composeEmail/CheckInvalidEmailRecipient.spec.ts
https://github.com/FlowCrypt/flowcrypt-ios/blob/master/appium/tests/specs/mock/composeEmail/CheckSendAsAlias.spec.ts

Notice how each test has some unique mock api configuration to work with, so it's clear which data the test needs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't mean this way, setting handlers.

I meant we would be setting configuration. Since now we have one MockApi per per test, we have an opportunity to configure mock api with different data (or expectations).

My suggestion doesn't rule out a configuration structure. It's just more straightforward to define endpoints in this way, for example:

const gmailData = GoogleData.withInitializedData(...).filter(...); // leave only a subset
t.mockApi?.setHandlers([
gmailGetMessage(gmailData), 
gmailSendMessage(gmailData)
]);
// do some tests
...
// read messages in gmailData

Thus we see what endpoints are expected to be used in this test

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for me, it'll just make tests setup more complicated if we'll need to set handlers separately for each test, while it won't give us any advantages in tests configuration.

While setting custom fesConfig, ekmConfig etc will allow us to have fully independent tests with different configs. They also can be updated during the test like this:

// test setup
mockApi.ekmConfig = { .. };
...
// some test code
...
mockApi.ekmConfig = { ... }; // updated config
// another test code
...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @sosnovsky in that @rrrooommmaaa 's approach seems more complex to set up for each test, without clear advantage compared to what was in the issue. Yes, it would allow to fine-tune which exact endpoints are allowed for the test, which would be more precise. But I don't think we need to go that far, and for tests that truly intend to test that, using @sosnovsky 's approach also doesn't mean we can't have a configuration to disallow certain exact endpoints for that test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's up to you to decide.
However, as of PR #4928, mockApi isn't exposed to the test definition, or am I missing something?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, currently it's not exposed, I was planning to add it to AvaContext:

t.mockApi = await startMockApiAndCopyBuild(t);

(here - https://github.com/FlowCrypt/flowcrypt-browser/blob/master/test/source/test.ts#L68)

And then use it in tests like this:

t.mockApi.fesConfig = { ... };
t.mockApi.ekmConfig = { ... };

const acct = `user3@standardsubdomainfes.localhost:${t.urls?.port}`; // added port to trick extension into calling the mock
const settingsPage = await BrowserRecipe.openSettingsLoginApprove(t, browser, acct);
await SetupPageRecipe.manualEnter(
Expand Down
3 changes: 3 additions & 0 deletions test/source/tests/tooling/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import { ExecutionContext } from 'ava';
import { TestUrls } from '../../browser/test-urls';
import { RequestType } from '../../mock/all-apis-mock';
import { Api } from '../../mock/lib/api';

import { Consts } from '../../test';

Expand All @@ -12,6 +14,7 @@ export type AvaContext = ExecutionContext<unknown> & {
attemptText?: string;
extensionDir?: string;
urls?: TestUrls;
mockApi?: Api<RequestType, unknown>;
};

const MAX_ATT_SIZE = 5 * 1024 * 1024;
Expand Down