Skip to content

Commit

Permalink
fix: remove circular dependency in packages (#1973)
Browse files Browse the repository at this point in the history
* fix: remove circular dependency b/w core and plugins packages

* chore: fix lint issues in test suites

* chore: fix lint issues in all test suites of plugins

* chore: fix import paths
  • Loading branch information
saikumarrs authored Dec 17, 2024
1 parent fa3f533 commit e525496
Show file tree
Hide file tree
Showing 47 changed files with 1,851 additions and 1,173 deletions.
Empty file.
10 changes: 10 additions & 0 deletions packages/analytics-js-common/__mocks__/BufferQueue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class BufferQueue<T> {
items: T[] = [];
enqueue = jest.fn();
dequeue = jest.fn();
isEmpty = jest.fn();
size = jest.fn();
clear = jest.fn();
}

export { BufferQueue };
16 changes: 16 additions & 0 deletions packages/analytics-js-common/__mocks__/ErrorHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { IErrorHandler, PreLoadErrorData } from '../src/types/ErrorHandler';
import { BufferQueue } from './BufferQueue';

// Mock all the methods of the ErrorHandler class
class ErrorHandler implements IErrorHandler {
onError = jest.fn();
leaveBreadcrumb = jest.fn();
notifyError = jest.fn();
init = jest.fn();
attachErrorListeners = jest.fn();
errorBuffer = new BufferQueue<PreLoadErrorData>();
}

const defaultErrorHandler = new ErrorHandler();

export { ErrorHandler, defaultErrorHandler };
18 changes: 18 additions & 0 deletions packages/analytics-js-common/__mocks__/Logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { ILogger } from '../src/types/Logger';

class Logger implements ILogger {
warn = jest.fn();
log = jest.fn();
error = jest.fn();
info = jest.fn();
debug = jest.fn();
minLogLevel = 0;
scope = 'test scope';
setMinLogLevel = jest.fn();
setScope = jest.fn();
logProvider = console;
}

const defaultLogger = new Logger();

export { Logger, defaultLogger };
116 changes: 116 additions & 0 deletions packages/analytics-js-common/__mocks__/Storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { cookie } from '../src/component-cookie';
import type { Nullable } from '../src/types/Nullable';
import type { IStorage } from '../src/types/Store';
import store from 'storejs';

class LocalStorage implements IStorage {
keys = () => {
return store.keys();
};
isEnabled = true;
getItem = (key: string) => {
return store.get(key) ?? null;
};
setItem = (key: string, value: any) => {
store.set(key, value);
};
removeItem = (key: string) => store.remove(key);
clear = () => {
store.clear();
};
length = store.len();
key = (idx: number): Nullable<string> => {
return this.keys()[idx] ?? null;
};
}

/**
* A storage utility to retain values in memory via Storage interface
*/
class InMemoryStorage implements IStorage {
isEnabled = true;
length = 0;
data: Record<string, any> = {};

setItem(key: string, value: any): any {
this.data[key] = value;
this.length = Object.keys(this.data).length;
return value;
}

getItem(key: string): any {
if (key in this.data) {
return this.data[key];
}
return null;
}

removeItem(key: string) {
if (key in this.data) {
delete this.data[key];
}
this.length = Object.keys(this.data).length;
return null;
}

clear() {
this.data = {};
this.length = 0;
}

key(index: number): Nullable<string> {
const curKeys = this.keys();
return curKeys[index] ?? null;
}

keys(): string[] {
return Object.keys(this.data);
}
}

class CookieStorage implements IStorage {
keys = () => {
return Object.keys(cookie());
};

isEnabled = true;

getItem = (key: string) => {
const value = cookie(key);
return value ?? null;
};

setItem = (key: string, value: any) => {
cookie(key, value);
this.length = Object.keys(cookie()).length;
};

removeItem = (key: string) => {
const result = this.setItem(key, null);
this.length = Object.keys(cookie()).length;
return result;
};

clear = () => {
// Not implemented
};

length = Object.keys(cookie()).length;

key = (idx: number): Nullable<string> => {
const curKeys = this.keys();
return curKeys[idx] ?? null;
};
}

const defaultCookieStorage = new CookieStorage();

export { CookieStorage, defaultCookieStorage };

const defaultInMemoryStorage = new InMemoryStorage();

export { InMemoryStorage, defaultInMemoryStorage };

const defaultLocalStorage = new LocalStorage();

export { LocalStorage, defaultLocalStorage };
56 changes: 56 additions & 0 deletions packages/analytics-js-common/__mocks__/Store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import type { IStore, IStoreConfig } from '../src/types/Store';
import { defaultInMemoryStorage, defaultLocalStorage } from './Storage';

// Mock all the methods of the Store class

class Store implements IStore {
constructor(config: IStoreConfig, engine?: any) {
this.id = config.id;
this.name = config.name;
this.isEncrypted = config.isEncrypted ?? false;
this.validKeys = config.validKeys ?? {};
this.engine = engine ?? defaultLocalStorage;
this.originalEngine = this.engine;
}
id = 'test';
name = 'test';
isEncrypted = false;
validKeys: Record<string, string>;
engine = defaultLocalStorage;
originalEngine = defaultLocalStorage;
createValidKey = (key: string) => {
return [this.name, this.id, key].join('.');
};
swapQueueStoreToInMemoryEngine = () => {
this.engine.keys().forEach((key: string) => {
const value = this.engine.getItem(key);
defaultInMemoryStorage.setItem(key, value);
});

this.engine = defaultInMemoryStorage;
};
set = (key: string, value: any) => {
const validKey = this.createValidKey(key);
this.engine.setItem(validKey, value);
};
get = (key: string) => {
const validKey = this.createValidKey(key);
return this.engine.getItem(validKey);
};
remove = (key: string) => {
const validKey = this.createValidKey(key);
this.engine.removeItem(validKey);
};
clear = () => {
this.engine.clear();
};
onError = jest.fn();
crypto = jest.fn();
encrypt = jest.fn();
decrypt = jest.fn();
getOriginalEngine = () => this.originalEngine;
}

const defaultStore = new Store({ id: 'test', name: 'test' });

export { Store, defaultStore };
32 changes: 32 additions & 0 deletions packages/analytics-js-common/__mocks__/StoreManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { IStoreConfig, IStoreManager } from '../src/types/Store';
import { defaultCookieStorage, defaultInMemoryStorage, defaultLocalStorage } from './Storage';
import { defaultStore, Store } from './Store';

// Mock all the methods of the StoreManager class

class StoreManager implements IStoreManager {
init = jest.fn();
setStore = (config: IStoreConfig) => {
let storageEngine;
switch (config.type) {
case 'localStorage':
storageEngine = defaultLocalStorage;
break;
case 'cookieStorage':
storageEngine = defaultCookieStorage;
break;
case 'memoryStorage':
default:
storageEngine = defaultInMemoryStorage;
break;
}

return new Store(config, storageEngine);
};
getStore = jest.fn(() => defaultStore);
initializeStorageState = jest.fn();
}

const defaultStoreManager = new StoreManager();

export { StoreManager, defaultStoreManager };
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import type { ILogger } from '@rudderstack/analytics-js-common/types/Logger';
import { cookie } from '../../src/component-cookie';

class MockLogger implements ILogger {
error = jest.fn();
}

const mockLoggerInstance = new MockLogger();
import { defaultLogger } from '../../__mocks__/Logger';

beforeEach(() => {
const allCookies = cookie();
Expand Down Expand Up @@ -38,9 +32,9 @@ describe('cookies', () => {
cookie('bad', '%');
cookie('bad', null);

cookie('bad', '\ud83d', undefined, mockLoggerInstance);
expect(mockLoggerInstance.error).toHaveBeenCalledTimes(1);
expect(mockLoggerInstance.error).toHaveBeenNthCalledWith(
cookie('bad', '\ud83d', undefined, defaultLogger);
expect(defaultLogger.error).toHaveBeenCalledTimes(1);
expect(defaultLogger.error).toHaveBeenNthCalledWith(
1,
'Failed to encode the cookie data.',
expect.any(Error),
Expand Down Expand Up @@ -102,6 +96,7 @@ describe('cookie()', () => {
it('should return all cookies if the first argument is not a valid string', () => {
cookie('name', 'loki');
cookie('species', 'ferret');
// @ts-expect-error testing invalid input
const obj = cookie(false);

expect(2).toEqual(Object.keys(obj).length);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isNull } from '@rudderstack/analytics-js-common/utilities/checks';
import type { Nullable } from '@rudderstack/analytics-js-common/types/Nullable';
import type { CookieOptions } from '@rudderstack/analytics-js-common/types/Storage';
import type { ILogger } from '@rudderstack/analytics-js-common/types/Logger';
import { isNull } from '../utilities/checks';
import type { Nullable } from '../types/Nullable';
import type { CookieOptions } from '../types/Storage';
import type { ILogger } from '../types/Logger';
import { COOKIE_DATA_ENCODING_ERROR } from '../constants/logMessages';

/**
Expand Down Expand Up @@ -119,7 +119,7 @@ const cookie = function (
value?: Nullable<string | number>,
options?: CookieOptions,
logger?: ILogger,
): void | any {
): any {
switch (arguments.length) {
case 4:
case 3:
Expand Down
3 changes: 3 additions & 0 deletions packages/analytics-js-common/src/constants/logMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const JSON_STRINGIFY_WARNING = `Failed to convert the value to a JSON string.`;
const BAD_DATA_WARNING = (context: string, key: string): string =>
`${context}${LOG_CONTEXT_SEPARATOR}A bad data (like circular reference, BigInt) has been detected in the object and the property "${key}" has been dropped from the output.`;

const COOKIE_DATA_ENCODING_ERROR = `Failed to encode the cookie data.`;

export {
LOG_CONTEXT_SEPARATOR,
SCRIPT_ALREADY_EXISTS_ERROR,
Expand All @@ -25,4 +27,5 @@ export {
CIRCULAR_REFERENCE_WARNING,
JSON_STRINGIFY_WARNING,
BAD_DATA_WARNING,
COOKIE_DATA_ENCODING_ERROR,
};
2 changes: 1 addition & 1 deletion packages/analytics-js-common/src/types/PluginEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface ExtensionPlugin {
| string
| (() => void)
| ExtensionPoint
| ((...args: any[]) => unknown | void)
| ((...args: any[]) => unknown)
| string[]
| undefined;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/analytics-js-cookies/src/cookiesUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import type { Nullable } from '@rudderstack/analytics-js-common/types/Nullable';
import { isNull, isNullOrUndefined } from '@rudderstack/analytics-js-common/utilities/checks';
import type { ApiObject } from '@rudderstack/analytics-js-common/types/ApiObject';
import { stringifyWithoutCircular } from '@rudderstack/analytics-js-common/utilities/json';
import { cookie } from '@rudderstack/analytics-js-common/component-cookie';
import { COOKIE_KEYS, ENCRYPTION_PREFIX_V3 } from './constants/cookies';
import { cookie } from './component-cookie';

const getEncryptedValueInternal = (
value: string | ApiObject,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LINE_ITEMS_CONFIG } from '@rudderstack/analytics-js-common/src/constants/integrations/CommonIntegrationsConstant/constants';
import { LINE_ITEMS_CONFIG } from '@rudderstack/analytics-js-common/constants/integrations/CommonIntegrationsConstant/constants';
import { payloadBuilder, payloadBuilderInList } from '../../../src/integrations/Podsights/utils';

describe('payloadBuilder', () => {
Expand Down
4 changes: 3 additions & 1 deletion packages/analytics-js-plugins/__fixtures__/fixtures.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { RudderEvent } from '@rudderstack/analytics-js-common/types/Event';

const sdkName = 'RudderLabs JavaScript SDK';
const rudderEventPage = {
properties: {
Expand Down Expand Up @@ -77,7 +79,7 @@ const rudderEventPage = {
userId: 'customUserID',
anonymousId: '1901c08d-d505-41cd-81a6-060457fad648',
event: null,
};
} as unknown as RudderEvent;

const errorMessage = 'Invalid request payload';

Expand Down
2 changes: 1 addition & 1 deletion packages/analytics-js-plugins/__fixtures__/msw.handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const handlers = [
status: 500,
});
}),
http.get(`https://asdf.com/bugsnag.min.js`, () => {
http.get(`__RS_BUGSNAG_SDK_URL__`, () => {
return new HttpResponse(errorMessage, {
status: 404,
});
Expand Down
Empty file.
17 changes: 17 additions & 0 deletions packages/analytics-js-plugins/__mocks__/HttpClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { IErrorHandler } from '@rudderstack/analytics-js-common/types/ErrorHandler';
import type { IHttpClient } from '@rudderstack/analytics-js-common/types/HttpClient';
import type { ILogger } from '@rudderstack/analytics-js-common/types/Logger';

class HttpClient implements IHttpClient {
errorHandler?: IErrorHandler;
logger?: ILogger;
hasErrorHandler = false;
getData = jest.fn();
getAsyncData = jest.fn();
setAuthHeader = jest.fn();
resetAuthHeader = jest.fn();
}

const defaultHttpClient = new HttpClient();

export { HttpClient, defaultHttpClient };
Loading

0 comments on commit e525496

Please sign in to comment.