diff --git a/.circleci/config.yml b/.circleci/config.yml index 3293c65d1..afebbdeaf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -401,22 +401,33 @@ jobs: prepare_steps: type: steps default: [] + api_endpoint: + type: string + dashboard_token_env: + type: string working_directory: ~/project executor: name: node/default steps: - advanced-checkout/shallow-checkout + - run: git clone git@github.com:Instabug/Escape.git + - run: + working_directory: Escape + command: swift build -c release + - run: + working_directory: Escape/.build/release + command: cp -f Escape /usr/local/bin/escape - steps: << parameters.prepare_steps >> - install_node_modules - run: name: Build the SDK command: yarn build - run: - name: Authorize with NPM - command: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc - - run: - name: Publish new enterprise version - command: npm publish + name: Publish Custom Package with Escape + command: Escape react-native publish-custompackage + environment: + DASHBOARD_TOKEN: << parameters.dashboard_token_env >> + DASHBOARD_API_ENDPOINT: << parameters.api_endpoint >> publish: macos: @@ -438,8 +449,11 @@ jobs: working_directory: project command: yarn build - run: + name: Publish Official Package with Escape working_directory: project command: Escape react-native publish + environment: + DASHBOARD_API_ENDPOINT: api.instabug.com publish_new_namespace: working_directory: ~/project executor: @@ -562,6 +576,8 @@ workflows: npm_package: '@instabug/react-native-nn' android_package: nn api_endpoint: st001009nn.instabug.com + api_endpoint: st001009nn.instabug.com + dashboard_token_env: ${NN_TOKEN} - hold_release_injazat: requires: *release_dependencies @@ -581,6 +597,8 @@ workflows: npm_package: '@instabug/react-native-injazat' android_package: injazat api_endpoint: st001013mec1.instabug.com + api_endpoint: st001013mec1.instabug.com + dashboard_token_env: ${INJAZAT_TOKEN} # Dream11 tests - hold_test_dream11: @@ -622,3 +640,5 @@ workflows: only: dream11 prepare_steps: - prepare_dream11 + api_endpoint: st001012dream11.instabug.com + dashboard_token_env: ${DREAM11_TOKEN} diff --git a/CHANGELOG.md b/CHANGELOG.md index 77f97581f..1be446044 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ - Added more search capabilities to the find-token.sh script. e.g., searching in .env file for react config. [#1366](https://github.com/Instabug/Instabug-React-Native/pull/1366) +- Updated the CHANGELOG on the dashboard for the enterprise users. [#1404](https://github.com/Instabug/Instabug-React-Native/pull/1404) + ## [14.3.0](https://github.com/Instabug/Instabug-React-Native/compare/v14.1.0...14.3.0) ### Added diff --git a/src/utils/InstabugUtils.ts b/src/utils/InstabugUtils.ts index b70153a7d..2a619f31d 100644 --- a/src/utils/InstabugUtils.ts +++ b/src/utils/InstabugUtils.ts @@ -74,7 +74,7 @@ export const getActiveRouteName = (navigationState: NavigationStateV4): string | return route.routeName; }; -function getFullRoute(state: NavigationStateV5 | PartialState): string { +export function getFullRoute(state: NavigationStateV5 | PartialState): string { try { if (!state.routes[state.index!].state) { return state.routes[state.index!].name; diff --git a/test/utils/InstabugUtils.spec.ts b/test/utils/InstabugUtils.spec.ts index deb2eebd0..11a5c8d1a 100644 --- a/test/utils/InstabugUtils.spec.ts +++ b/test/utils/InstabugUtils.spec.ts @@ -7,16 +7,7 @@ import * as Instabug from '../../src/modules/Instabug'; import * as NetworkLogger from '../../src/modules/NetworkLogger'; import { NativeCrashReporting } from '../../src/native/NativeCrashReporting'; import { InvocationEvent, NetworkData, NonFatalErrorLevel } from '../../src'; -import InstabugUtils, { - getStackTrace, - registerFilteringAndObfuscationListener, - registerFilteringListener, - registerObfuscationListener, - reportNetworkLog, - resetNativeObfuscationListener, - sendCrashReport, - updateNetworkLogSnapshot, -} from '../../src/utils/InstabugUtils'; +import * as InstabugUtils from '../../src/utils/InstabugUtils'; import { NativeNetworkLogger, @@ -203,9 +194,9 @@ describe('Instabug Utils', () => { const remoteSenderCallback = NativeCrashReporting.sendHandledJSCrash; Platform.OS = 'android'; const errorMock = new TypeError('Invalid type'); - const jsStackTrace = getStackTrace(errorMock); + const jsStackTrace = InstabugUtils.getStackTrace(errorMock); - sendCrashReport(errorMock, (data) => + InstabugUtils.sendCrashReport(errorMock, (data) => remoteSenderCallback(data, null, null, NonFatalErrorLevel.error), ); @@ -231,9 +222,9 @@ describe('Instabug Utils', () => { const remoteSenderCallback = NativeCrashReporting.sendHandledJSCrash; Platform.OS = 'ios'; const errorMock = new TypeError('Invalid type'); - const jsStackTrace = getStackTrace(errorMock); + const jsStackTrace = InstabugUtils.getStackTrace(errorMock); - sendCrashReport(errorMock, (data) => + InstabugUtils.sendCrashReport(errorMock, (data) => remoteSenderCallback(data, null, null, NonFatalErrorLevel.error), ); const expectedMap = { @@ -290,7 +281,7 @@ describe('reportNetworkLog', () => { const requestHeaders = JSON.stringify(network.requestHeaders); const responseHeaders = JSON.stringify(network.responseHeaders); - reportNetworkLog(network); + InstabugUtils.reportNetworkLog(network); expect(NativeInstabug.networkLogAndroid).toHaveBeenCalledTimes(1); expect(NativeInstabug.networkLogAndroid).toHaveBeenCalledWith( @@ -335,7 +326,7 @@ describe('reportNetworkLog', () => { it('reportNetworkLog should send network logs to native with the correct parameters on iOS', () => { Platform.OS = 'ios'; - reportNetworkLog(network); + InstabugUtils.reportNetworkLog(network); expect(NativeInstabug.networkLogIOS).toHaveBeenCalledTimes(1); expect(NativeInstabug.networkLogIOS).toHaveBeenCalledWith( @@ -397,7 +388,7 @@ describe('test registerNetworkLogsListener usage', () => { }; it('registerObfuscationListener should call NetworkLogger.registerNetworkLogsListener() with NetworkListenerType = NetworkListenerType.obfuscation', () => { - registerObfuscationListener(); + InstabugUtils.registerObfuscationListener(); expect(NetworkLogger.registerNetworkLogsListener).toBeCalledTimes(1); expect(NetworkLogger.registerNetworkLogsListener).toBeCalledWith( NetworkListenerType.obfuscation, @@ -407,7 +398,7 @@ describe('test registerNetworkLogsListener usage', () => { it('registerFilteringListener should call NetworkLogger.registerNetworkLogsListener() with NetworkListenerType = NetworkListenerType.filtering', () => { const testText = 'true'; - registerFilteringListener(testText); + InstabugUtils.registerFilteringListener(testText); expect(NetworkLogger.registerNetworkLogsListener).toBeCalledTimes(1); expect(NetworkLogger.registerNetworkLogsListener).toBeCalledWith( @@ -418,7 +409,7 @@ describe('test registerNetworkLogsListener usage', () => { it('registerFilteringAndObfuscationListener should call NetworkLogger.registerNetworkLogsListener() with NetworkListenerType = NetworkListenerType.both', () => { const testText = 'true'; - registerFilteringAndObfuscationListener(testText); + InstabugUtils.registerFilteringAndObfuscationListener(testText); expect(NetworkLogger.registerNetworkLogsListener).toBeCalledTimes(1); expect(NetworkLogger.registerNetworkLogsListener).toBeCalledWith( @@ -429,7 +420,7 @@ describe('test registerNetworkLogsListener usage', () => { it('should call NetworkLoggerEmitter.removeAllListeners when call resetNativeObfuscationListener', () => { jest.spyOn(NetworkLoggerEmitter, 'removeAllListeners').mockImplementation(); - resetNativeObfuscationListener(); + InstabugUtils.resetNativeObfuscationListener(); expect(NetworkLoggerEmitter.removeAllListeners).toBeCalledTimes(1); }); @@ -437,7 +428,7 @@ describe('test registerNetworkLogsListener usage', () => { Platform.OS = 'android'; jest.spyOn(NativeNetworkLogger, 'resetNetworkLogsListener').mockImplementation(); jest.spyOn(NetworkLoggerEmitter, 'removeAllListeners').mockImplementation(); - resetNativeObfuscationListener(); + InstabugUtils.resetNativeObfuscationListener(); expect(NativeNetworkLogger.resetNetworkLogsListener).toBeCalledTimes(1); expect(NetworkLoggerEmitter.removeAllListeners).toBeCalledTimes(1); }); @@ -445,7 +436,7 @@ describe('test registerNetworkLogsListener usage', () => { it('should call NativeNetworkLogger.updateNetworkLogSnapshot when call updateNetworkLogSnapshot with correct parameters', () => { jest.spyOn(NativeNetworkLogger, 'updateNetworkLogSnapshot').mockImplementation(); - updateNetworkLogSnapshot(network); + InstabugUtils.updateNetworkLogSnapshot(network); expect(NativeNetworkLogger.updateNetworkLogSnapshot).toBeCalledTimes(1); expect(NativeNetworkLogger.updateNetworkLogSnapshot).toHaveBeenCalledWith( network.url, @@ -458,3 +449,98 @@ describe('test registerNetworkLogsListener usage', () => { ); }); }); + +describe('InstabugUtils', () => { + it('setApmNetworkFlagsIfChanged should return true if flags change', () => { + const flags = { + isNativeInterceptionFeatureEnabled: true, + hasAPMNetworkPlugin: true, + shouldEnableNativeInterception: true, + }; + expect(InstabugUtils.setApmNetworkFlagsIfChanged(flags)).toBe(true); + expect(InstabugUtils.setApmNetworkFlagsIfChanged(flags)).toBe(false); + }); + + it('generateTracePartialId should return a non-zero hex string and number', () => { + const { numberPartilId, hexStringPartialId } = InstabugUtils.generateTracePartialId(); + expect(hexStringPartialId).toMatch(/^[0-9a-f]{8}$/); + expect(hexStringPartialId).not.toBe('00000000'); + expect(typeof numberPartilId).toBe('number'); + expect(numberPartilId).not.toBe(0); + }); + + it('generateW3CHeader should return a valid w3c header object', () => { + const now = Date.now(); + const result = InstabugUtils.generateW3CHeader(now); + expect(result).toHaveProperty('timestampInSeconds'); + expect(result).toHaveProperty('partialId'); + expect(result).toHaveProperty('w3cHeader'); + expect(typeof result.w3cHeader).toBe('string'); + expect(result.w3cHeader.split('-').length).toBe(4); + }); + + it('isContentTypeNotAllowed should return false for allowed types and true for not allowed', () => { + expect(InstabugUtils.isContentTypeNotAllowed('application/json')).toBe(false); + expect(InstabugUtils.isContentTypeNotAllowed('text/plain')).toBe(false); + expect(InstabugUtils.isContentTypeNotAllowed('image/png')).toBe(true); + expect(InstabugUtils.isContentTypeNotAllowed('application/pdf')).toBe(true); + }); +}); + +describe('checkNetworkRequestHandlers', () => { + let registerNetworkLogsListenerSpy: jest.SpyInstance; + + beforeEach(() => { + jest.clearAllMocks(); + registerNetworkLogsListenerSpy = jest + .spyOn(NetworkLogger, 'registerNetworkLogsListener') + .mockImplementation(jest.fn()); + }); + + it('should register for both if obfuscation handler and filter expression exist', () => { + jest.spyOn(NetworkLogger, 'getNetworkDataObfuscationHandler').mockReturnValue(jest.fn()); + jest.spyOn(NetworkLogger, 'hasRequestFilterExpression').mockReturnValue(true); + jest.spyOn(NetworkLogger, 'getRequestFilterExpression').mockReturnValue('true'); + + InstabugUtils.checkNetworkRequestHandlers(); + + expect(registerNetworkLogsListenerSpy).toHaveBeenCalledWith( + NetworkListenerType.both, + expect.any(Function), + ); + }); + + it('should register for obfuscation only if only obfuscation handler exists', () => { + jest.spyOn(NetworkLogger, 'getNetworkDataObfuscationHandler').mockReturnValue(jest.fn()); + jest.spyOn(NetworkLogger, 'hasRequestFilterExpression').mockReturnValue(false); + + InstabugUtils.checkNetworkRequestHandlers(); + + expect(registerNetworkLogsListenerSpy).toHaveBeenCalledWith( + NetworkListenerType.obfuscation, + expect.any(Function), + ); + }); + + it('should register for filtering only if only filter expression exists', () => { + jest.spyOn(NetworkLogger, 'getNetworkDataObfuscationHandler').mockReturnValue(undefined); + jest.spyOn(NetworkLogger, 'hasRequestFilterExpression').mockReturnValue(true); + jest.spyOn(NetworkLogger, 'getRequestFilterExpression').mockReturnValue('true'); + + InstabugUtils.checkNetworkRequestHandlers(); + + expect(registerNetworkLogsListenerSpy).toHaveBeenCalledWith( + NetworkListenerType.filtering, + expect.any(Function), + ); + }); + + it('should not register any listener if neither exist', () => { + jest.spyOn(NetworkLogger, 'getNetworkDataObfuscationHandler').mockReturnValue(undefined); + jest.spyOn(NetworkLogger, 'hasRequestFilterExpression').mockReturnValue(false); + + InstabugUtils.checkNetworkRequestHandlers(); + + expect(registerNetworkLogsListenerSpy).not.toHaveBeenCalled(); + }); +});