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

[No QA] [TS migration] Migrate 'E2E' lib to TypeScript #28896

Merged
merged 26 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
65c2205
[TS migration] Migrate 'E2E' lib
VickyStash Oct 4, 2023
cbf918c
Merge branch 'main' into ts-migration/e2e-lib
VickyStash Oct 5, 2023
61aa3d8
Add errors field to report action type
VickyStash Oct 5, 2023
ba6802d
Merge branch 'main' into ts-migration/e2e-lib
VickyStash Oct 16, 2023
354cd4c
Migrate e2e files to TS
VickyStash Oct 16, 2023
82fb834
Merge branch 'main' into ts-migration/e2e-lib
VickyStash Oct 17, 2023
af68ede
Update files extension in docs
VickyStash Oct 17, 2023
8b9f6ff
Merge branch 'main' into ts-migration/e2e-lib
VickyStash Oct 18, 2023
bc08d2a
Remove todo
VickyStash Oct 18, 2023
ed0bfd3
Merge branch 'main' into ts-migration/e2e-lib
VickyStash Oct 23, 2023
21bf425
Fix ts error
VickyStash Oct 23, 2023
61c5075
Merge branch 'main' into ts-migration/e2e-lib
VickyStash Oct 30, 2023
551e96a
Update imports after merging main, fix ts errors
VickyStash Oct 30, 2023
5bf3423
Merge branch 'main' into ts-migration/e2e-lib
VickyStash Oct 30, 2023
3e0627a
Fix prettier
VickyStash Oct 30, 2023
e912bc2
Merge branch 'main' into ts-migration/e2e-lib
VickyStash Nov 6, 2023
1eaac4c
Fix NaN in cooling down logs
VickyStash Nov 6, 2023
a3361ca
Merge branch 'main' into ts-migration/e2e-lib
VickyStash Nov 7, 2023
581dfcd
Migrate new files to TS; fix TS issues after merging main
VickyStash Nov 7, 2023
fe890c9
Merge branch 'main' into ts-migration/e2e-lib
VickyStash Nov 9, 2023
7d0075e
Fix ts issues after main merging
VickyStash Nov 9, 2023
876fc14
Update file extension
VickyStash Nov 9, 2023
f7763cf
Merge branch 'main' into ts-migration/e2e-lib
VickyStash Nov 13, 2023
a5d2248
Remove extra params from Report type
VickyStash Nov 13, 2023
4479acc
Merge branch 'main' into ts-migration/e2e-lib
VickyStash Nov 13, 2023
d790b48
Fix ts issues
VickyStash Nov 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ package-lock.json
*.scss
*.md
# We need to modify the import here specifically, hence we disable prettier to get rid of the sorted imports
src/libs/E2E/reactNativeLaunchingTest.js
src/libs/E2E/reactNativeLaunchingTest.ts
6 changes: 3 additions & 3 deletions fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ opt_out_usage

platform :android do
desc "Generate a new local APK for e2e testing"

lane :build_e2e do
ENV["ENVFILE"]="tests/e2e/.env.e2e"
ENV["ENTRY_FILE"]="src/libs/E2E/reactNativeLaunchingTest.js"
ENV["ENTRY_FILE"]="src/libs/E2E/reactNativeLaunchingTest.ts"
ENV["E2E_TESTING"]="true"

gradle(
Expand All @@ -31,7 +31,7 @@ platform :android do

lane :build_e2edelta do
ENV["ENVFILE"]="tests/e2e/.env.e2edelta"
ENV["ENTRY_FILE"]="src/libs/E2E/reactNativeLaunchingTest.js"
ENV["ENTRY_FILE"]="src/libs/E2E/reactNativeLaunchingTest.ts"
ENV["E2E_TESTING"]="true"

gradle(
Expand Down
2 changes: 1 addition & 1 deletion metro.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const config = {
const resolution = context.resolveRequest(context, moduleName, platform);
if (isE2ETesting && moduleName.includes('/API')) {
const originalPath = resolution.filePath;
const mockPath = originalPath.replace('src/libs/API.ts', 'src/libs/E2E/API.mock.js').replace('/src/libs/API.js/', 'src/libs/E2E/API.mock.js');
const mockPath = originalPath.replace('src/libs/API.ts', 'src/libs/E2E/API.mock.ts').replace('/src/libs/API.ts/', 'src/libs/E2E/API.mock.ts');
// eslint-disable-next-line no-console
console.log('⚠️⚠️⚠️⚠️ Replacing resolution path', originalPath, ' => ', mockPath);

Expand Down
70 changes: 70 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,76 @@ const CONST = {
CUSTOM_STATUS: 'customStatus',
NEW_DOT_TAGS: 'newDotTags',
NEW_DOT_SAML: 'newDotSAML',
PDF_META_STORE: 'pdfMetaStore',
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you give a bit of context here? What is the source of all these new properties?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@blazejkustra CONST.BETAS is used in Beta type
There are two apiMocks that set betas, inside openApp.ts and signinUser.ts

So without these new properties, it gives an error like this:
image

Copy link
Contributor

Choose a reason for hiding this comment

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

I am working on removing all useless ones, and this change made it 10x harder in this repo 😞

Copy link
Contributor

Choose a reason for hiding this comment

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

@flodnv Why it made harder for you? Can you give a bit more context?

Copy link
Contributor

Choose a reason for hiding this comment

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

Because now I have to check if all of these betas are used, which they probably are not...

It would have been better to update the mocks to match the code instead of the opposite, which I think is probably almost always preferred (why mock something that does not exist / is not used?)

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed here: #31783

REPORT_ACTION_CONTEXT_MENU: 'reportActionContextMenu',
SUBMIT_POLICY: 'submitPolicy',
ATTENDEES: 'attendees',
AUTO_EXPORT: 'autoExport',
AUTO_EXPORT_INTACCT: 'autoExportIntacct',
AUTO_EXPORT_QBO: 'autoExportQbo',
AUTO_EXPORT_XERO: 'autoExportXero',
AUTO_JOIN_POLICY: 'autoJoinPolicy',
AUTOMATED_TAX_EXEMPTION: 'automatedTaxExemption',
BILL_PAY: 'billPay',
CATEGORY_DEFAULT_TAX: 'categoryDefaultTax',
COLLECTABLE_DEPOSIT_ACCOUNTS: 'collectableDepositAccounts',
CONCIERGE_TRAVEL: 'conciergeTravel',
CONNECTED_CARDS: 'connectedCards',
DISCREPANCY: 'discrepancy',
DOMAIN_CONTACT_BILLING: 'domainContactBilling',
DOMAIN_TWO_FACTOR_AUTH: 'domainTwoFactorAuth',
DUPLICATE_DETECTION: 'duplicateDetection',
EMAIL_SUPPRESSION_BETA: 'emailSuppressionBeta',
EXPENSES_V2: 'expensesV2',
EXPENSIFY_CARD: 'expensifyCard',
EXPENSIFY_CARD_INTACCT_RECONCILIATION: 'expensifyCardIntacctReconciliation',
EXPENSIFY_CARD_NETSUITE_RECONCILIATION: 'expensifyCardNetSuiteReconciliation',
EXPENSIFY_CARD_QBO_RECONCILIATION: 'expensifyCardQBOReconciliation',
EXPENSIFY_CARD_RAPID_INCREASE_FRAUD: 'expensifyCardRapidIncreaseFraud',
EXPENSIFY_CARD_XERO_RECONCILIATION: 'expensifyCardXeroReconciliation',
EXPENSIFY_ORG: 'expensifyOrg',
FIX_VIOLATION_PUSH_NOTIFICATION: 'fixViolationPushNotification',
FREE_PLAN_FULL_LAUNCH: 'freePlanFullLaunch',
FREE_PLAN_SOFT_LAUNCH: 'freePlanSoftLaunch',
GUSTO: 'gusto',
INBOX_CACHE: 'inboxCache',
INBOX_HIDDEN_TASKS: 'inboxHiddenTasks',
INDIRECT_INTEGRATION_SETUP: 'indirectIntegrationSetup',
IOU: 'IOU',
JOIN_POLICY: 'joinPolicy',
LOAD_POLICY_ASYNC: 'loadPolicyAsync',
MAP_RECEIPT: 'mapReceipt',
MERGE_API: 'mergeAPI',
MOBILE_REALTIME_REPORT_COMMENTS: 'mobileRealtimeReportComments',
MOBILE_SECURE_RECEIPTS: 'mobileSecureReceipts',
MONTHLY_SETTLEMENT: 'monthlySettlement',
NAMES_AND_AVATARS: 'namesAndAvatars',
NATIVE_CHAT: 'nativeChat',
NEW_PRICING: 'newPricing',
NEWSLETTER_THREE: 'newsletterThree',
NEXT_STEPS: 'nextSteps',
OPEN_FACE_HAMBURGER: 'openFaceHamburger',
PER_DIEM: 'perDiem',
PER_DIEM_INTERNATIONAL: 'perDiemInternational',
PRICING_COPY_CHANGES: 'pricingCopyChanges',
QBO_INVOICES: 'qboInvoices',
QUICKBOOKS_DESKTOP_V2: 'quickbooksDesktopV2',
REALTIME_REPORT_COMMENTS: 'realtimeReportComments',
S2W_ANNOUNCEMENT: 's2wAnnouncement',
SCHEDULED_AUTO_REPORTING: 'scheduledAutoReporting',
SECURE_RECEIPTS: 'secureReceipts',
SECURE_RECEIPTS_REPORTS: 'secureReceiptsReports',
SELF_SERVICE_HARD_LAUNCH: 'selfServiceHardLaunch',
SEND_MONEY: 'sendMoney',
SMART_SCAN_USER_DISPUTES: 'smartScanUserDisputes',
SMS_SIGN_UP: 'smsSignUp',
STRIPE_CONNECT: 'stripeConnect',
SUMMARY_EMAIL: 'summaryEmail',
SWIPE_TO_WIN: 'swipeToWin',
TAX_FOR_MILEAGE: 'taxForMileage',
TWO_FACTOR_AUTH: 'twoFactorAuth',
VENMO_INTEGRATION: 'venmoIntegration',
ZENEFITS_INTEGRATION: 'zenefitsIntegration',
VIOLATIONS: 'violations',
},
BUTTON_STATES: {
Expand Down
2 changes: 1 addition & 1 deletion src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ type OnyxValues = {
[ONYXKEYS.COUNTRY_CODE]: number;
[ONYXKEYS.COUNTRY]: string;
[ONYXKEYS.USER]: OnyxTypes.User;
[ONYXKEYS.LOGIN_LIST]: OnyxTypes.Login;
[ONYXKEYS.LOGIN_LIST]: Record<string, OnyxTypes.Login>;
[ONYXKEYS.SESSION]: OnyxTypes.Session;
[ONYXKEYS.BETAS]: OnyxTypes.Beta[];
[ONYXKEYS.NVP_PRIORITY_MODE]: ValueOf<typeof CONST.PRIORITY_MODE>;
Expand Down
41 changes: 19 additions & 22 deletions src/libs/E2E/API.mock.js → src/libs/E2E/API.mock.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
/* eslint-disable rulesdir/no-api-in-views */
import Onyx from 'react-native-onyx';
import _ from 'underscore';
import Log from '@libs/Log';
import mockAuthenticatePusher from './apiMocks/authenticatePusher';
import Response from '@src/types/onyx/Response';
// mock functions
import mockAuthenticatePusher from './apiMocks/authenticatePusher';
import mockBeginSignin from './apiMocks/beginSignin';
import mockOpenApp from './apiMocks/openApp';
import mockOpenReport from './apiMocks/openReport';
import mockReadNewestAction from './apiMocks/readNewestAction';
import mockSigninUser from './apiMocks/signinUser';

type ApiCommandParameters = Record<string, unknown>;

type Mocks = Record<string, (params: ApiCommandParameters) => Response>;

/**
* A dictionary which has the name of a API command as key, and a function which
* receives the api command parameters as value and is expected to return a response
* object.
*/
const mocks = {
const mocks: Mocks = {
BeginSignIn: mockBeginSignin,
SigninUser: mockSigninUser,
OpenApp: mockOpenApp,
Expand All @@ -26,14 +29,14 @@ const mocks = {
ReadNewestAction: mockReadNewestAction,
};

function mockCall(command, apiCommandParameters, tag) {
const mockResponse = mocks[command] && mocks[command](apiCommandParameters);
function mockCall(command: string, apiCommandParameters: ApiCommandParameters, tag: string): Promise<void> | Promise<Response> | undefined {
const mockResponse = mocks[command]?.(apiCommandParameters);
if (!mockResponse) {
Log.warn(`[${tag}] for command ${command} is not mocked yet! ⚠️`);
return;
}

if (_.isArray(mockResponse.onyxData)) {
if (Array.isArray(mockResponse.onyxData)) {
return Onyx.update(mockResponse.onyxData);
}

Expand All @@ -44,12 +47,10 @@ function mockCall(command, apiCommandParameters, tag) {
* All calls to API.write() will be persisted to disk as JSON with the params, successData, and failureData.
* This is so that if the network is unavailable or the app is closed, we can send the WRITE request later.
*
* @param {String} command - Name of API command to call.
* @param {Object} apiCommandParameters - Parameters to send to the API.
*
* @returns {Promise}
* @param command - Name of API command to call.
* @param apiCommandParameters - Parameters to send to the API.
*/
function write(command, apiCommandParameters = {}) {
function write(command: string, apiCommandParameters: ApiCommandParameters = {}): Promise<void> | Promise<Response> | undefined {
return mockCall(command, apiCommandParameters, 'API.write');
}

Expand All @@ -61,24 +62,20 @@ function write(command, apiCommandParameters = {}) {
* Using this method is discouraged and will throw an ESLint error. Use it sparingly and only when all other alternatives have been exhausted.
* It is best to discuss it in Slack anytime you are tempted to use this method.
*
* @param {String} command - Name of API command to call.
* @param {Object} apiCommandParameters - Parameters to send to the API.
*
* @returns {Promise}
* @param command - Name of API command to call.
* @param apiCommandParameters - Parameters to send to the API.
*/
function makeRequestWithSideEffects(command, apiCommandParameters = {}) {
function makeRequestWithSideEffects(command: string, apiCommandParameters: ApiCommandParameters = {}): Promise<void> | Promise<Response> | undefined {
return mockCall(command, apiCommandParameters, 'API.makeRequestWithSideEffects');
}

/**
* Requests made with this method are not be persisted to disk. If there is no network connectivity, the request is ignored and discarded.
*
* @param {String} command - Name of API command to call.
* @param {Object} apiCommandParameters - Parameters to send to the API.
*
* @returns {Promise}
* @param command - Name of API command to call.
* @param apiCommandParameters - Parameters to send to the API.
*/
function read(command, apiCommandParameters) {
function read(command: string, apiCommandParameters: ApiCommandParameters): Promise<void> | Promise<Response> | undefined {
return mockCall(command, apiCommandParameters, 'API.read');
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,16 @@ import ONYXKEYS from '@src/ONYXKEYS';
* If the user is already logged in the function will simply
* resolve.
*
* @param {String} email
* @param {String} password
* @return {Promise<boolean>} Resolved true when the user was actually signed in. Returns false if the user was already logged in.
* @return Resolved true when the user was actually signed in. Returns false if the user was already logged in.
*/
export default function (email = 'fake@email.com', password = 'Password123') {
const waitForBeginSignInToFinish = () =>
export default function (email = 'fake@email.com', password = 'Password123'): Promise<boolean> {
const waitForBeginSignInToFinish = (): Promise<void> =>
new Promise((resolve) => {
const id = Onyx.connect({
key: ONYXKEYS.CREDENTIALS,
callback: (credentials) => {
// beginSignUp writes to credentials.login once the API call is complete
if (!credentials.login) {
if (!credentials?.login) {
return;
}

Expand All @@ -36,7 +34,7 @@ export default function (email = 'fake@email.com', password = 'Password123') {
const connectionId = Onyx.connect({
key: ONYXKEYS.SESSION,
callback: (session) => {
if (session.authToken == null || session.authToken.length === 0) {
if (session?.authToken == null || session.authToken.length === 0) {
neededLogin = true;

// authenticate with a predefined user
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Keyboard} from 'react-native';

export default function waitForKeyboard() {
export default function waitForKeyboard(): Promise<void> {
return new Promise((resolve) => {
function checkKeyboard() {
if (Keyboard.isVisible()) {
Expand Down
6 changes: 0 additions & 6 deletions src/libs/E2E/apiMocks/authenticatePusher.js

This file was deleted.

11 changes: 11 additions & 0 deletions src/libs/E2E/apiMocks/authenticatePusher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Response from '@src/types/onyx/Response';

const authenticatePusher = (): Response => ({
auth: 'auth',
// eslint-disable-next-line @typescript-eslint/naming-convention
shared_secret: 'secret',
jsonCode: 200,
requestID: '783ef7fc3991969a-SJC',
});

export default authenticatePusher;
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
export default ({email}) => ({
import {SigninParams} from '@libs/E2E/types';
import Response from '@src/types/onyx/Response';

const beginSignin = ({email}: SigninParams): Response => ({
onyxData: [
{
onyxMethod: 'merge',
Expand All @@ -23,3 +26,5 @@ export default ({email}) => ({
jsonCode: 200,
requestID: '783e54ef4b38cff5-SJC',
});

export default beginSignin;
Loading
Loading