forked from Ivasoft/mattermost-mobile
[Gekidou] Refactor storage layer (#5471)
* Refactored storage layer - in progress * Refactored DatabaseManager & Operators * Renamed isRecordAppEqualToRaw to isRecordInfoEqualToRaw * Review feedback * Update app/database/models/app/info.ts Co-authored-by: Miguel Alatzar <migbot@users.noreply.github.com> * Update app/database/models/server/my_team.ts Co-authored-by: Miguel Alatzar <migbot@users.noreply.github.com> Co-authored-by: Avinash Lingaloo <> Co-authored-by: Miguel Alatzar <migbot@users.noreply.github.com>
This commit is contained in:
@@ -4,233 +4,84 @@
|
||||
import {Database, Q} from '@nozbe/watermelondb';
|
||||
|
||||
import {MM_TABLES} from '@constants/database';
|
||||
import {DatabaseType} from '@typings/database/enums';
|
||||
import IGlobal from '@typings/database/global';
|
||||
import IServers from '@typings/database/servers';
|
||||
|
||||
import DatabaseManager from '@database/manager';
|
||||
import ServerDataOperator from '@database/operator/server_data_operator';
|
||||
|
||||
jest.mock('@database/manager');
|
||||
import type IServers from '@typings/database/models/app/servers';
|
||||
|
||||
const {GLOBAL, SERVERS} = MM_TABLES.DEFAULT;
|
||||
const RECENTLY_VIEWED_SERVERS = 'RECENTLY_VIEWED_SERVERS';
|
||||
const {SERVERS} = MM_TABLES.APP;
|
||||
|
||||
// NOTE : On the mock Database Manager, we cannot test for :
|
||||
// 1. Android/iOS file path
|
||||
// 2. Deletion of the 'databases' folder on those two platforms
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
describe('*** Database Manager tests ***', () => {
|
||||
let databaseManagerClient: DatabaseManager | null;
|
||||
|
||||
beforeEach(() => {
|
||||
databaseManagerClient = new DatabaseManager();
|
||||
const serverUrls = ['https://appv1.mattermost.com', 'https://appv2.mattermost.com'];
|
||||
beforeAll(async () => {
|
||||
await DatabaseManager.init(serverUrls);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
databaseManagerClient = null;
|
||||
});
|
||||
|
||||
const createTwoConnections = async () => {
|
||||
await databaseManagerClient!.createDatabaseConnection({
|
||||
shouldAddToDefaultDatabase: true,
|
||||
configs: {
|
||||
actionsEnabled: true,
|
||||
dbName: 'connection1',
|
||||
dbType: DatabaseType.SERVER,
|
||||
serverUrl: 'https://appv1.mattermost.com',
|
||||
},
|
||||
});
|
||||
await databaseManagerClient!.createDatabaseConnection({
|
||||
shouldAddToDefaultDatabase: true,
|
||||
configs: {
|
||||
actionsEnabled: true,
|
||||
dbName: 'connection2',
|
||||
dbType: DatabaseType.SERVER,
|
||||
serverUrl: 'https://appv2.mattermost.com',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
it('=> should return a default database', async () => {
|
||||
expect.assertions(2);
|
||||
|
||||
const spyOnAddServerToDefaultDatabase = jest.spyOn(databaseManagerClient as any, 'addServerToDefaultDatabase');
|
||||
const appDatabase = DatabaseManager.appDatabase?.database;
|
||||
|
||||
const defaultDB = await databaseManagerClient!.getDefaultDatabase();
|
||||
|
||||
expect(defaultDB).toBeInstanceOf(Database);
|
||||
expect(spyOnAddServerToDefaultDatabase).not.toHaveBeenCalledTimes(1);
|
||||
expect(appDatabase).toBeInstanceOf(Database);
|
||||
expect(Object.keys(DatabaseManager.serverDatabases).length).toBe(2);
|
||||
});
|
||||
|
||||
it('=> should create a new server connection', async () => {
|
||||
expect.assertions(2);
|
||||
it('=> should create a new server database', async () => {
|
||||
expect.assertions(3);
|
||||
|
||||
const spyOnAddServerToDefaultDatabase = jest.spyOn(databaseManagerClient as any, 'addServerToDefaultDatabase');
|
||||
const spyOnAddServerToDefaultDatabase = jest.spyOn(DatabaseManager as any, 'addServerToAppDatabase');
|
||||
|
||||
const connection1 = await databaseManagerClient!.createDatabaseConnection({
|
||||
shouldAddToDefaultDatabase: true,
|
||||
configs: {
|
||||
actionsEnabled: true,
|
||||
const connection1 = await DatabaseManager!.createServerDatabase({
|
||||
config: {
|
||||
dbName: 'community mattermost',
|
||||
dbType: DatabaseType.SERVER,
|
||||
serverUrl: 'https://appv1.mattermost.com',
|
||||
},
|
||||
});
|
||||
|
||||
expect(connection1).toBeInstanceOf(Database);
|
||||
expect(connection1?.database).toBeInstanceOf(Database);
|
||||
expect(connection1?.operator).toBeInstanceOf(ServerDataOperator);
|
||||
expect(spyOnAddServerToDefaultDatabase).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('=> should switch between active server connections', async () => {
|
||||
expect.assertions(6);
|
||||
let adapter;
|
||||
it('=> should switch between active servers', async () => {
|
||||
expect.assertions(4);
|
||||
|
||||
const activeServerA = await databaseManagerClient!.getActiveServerDatabase();
|
||||
let activeServerUrl = await DatabaseManager.getActiveServerUrl();
|
||||
const serverA = await DatabaseManager.getActiveServerDatabase();
|
||||
|
||||
// as we haven't set an active server yet, we should be getting undefined in the activeServer variable
|
||||
expect(activeServerA).toBeUndefined();
|
||||
// as we haven't set an active server yet, so the first registered server should be the active one
|
||||
expect(activeServerUrl).toBe(serverUrls[0]);
|
||||
expect(serverA).toEqual(DatabaseManager.serverDatabases[serverUrls[0]].database);
|
||||
|
||||
const setActiveServer = async (serverUrl: string) => {
|
||||
// now we set the active database
|
||||
await databaseManagerClient!.setActiveServerDatabase(serverUrl);
|
||||
};
|
||||
await DatabaseManager.setActiveServerDatabase('https://appv2.mattermost.com');
|
||||
|
||||
await setActiveServer('https://appv1.mattermost.com');
|
||||
|
||||
// let's verify if we now have a value for activeServer
|
||||
const activeServerB = await databaseManagerClient!.getActiveServerDatabase();
|
||||
expect(activeServerB).toBeDefined();
|
||||
|
||||
adapter = activeServerB!.adapter as any;
|
||||
const currentDBName = adapter.underlyingAdapter._dbName;
|
||||
expect(currentDBName).toStrictEqual('appv1.mattermost.com');
|
||||
|
||||
// spice things up; we'll set a new server and verify if the value of activeServer changes
|
||||
await setActiveServer('https://appv2.mattermost.com');
|
||||
const activeServerC = await databaseManagerClient!.getActiveServerDatabase();
|
||||
expect(activeServerC).toBeDefined();
|
||||
|
||||
adapter = activeServerC!.adapter as any;
|
||||
const newDBName = adapter.underlyingAdapter._dbName;
|
||||
expect(newDBName).toStrictEqual('appv2.mattermost.com');
|
||||
|
||||
const defaultDatabase = await databaseManagerClient!.getDefaultDatabase();
|
||||
const records = await defaultDatabase!.collections.get(MM_TABLES.DEFAULT.GLOBAL).query(Q.where('name', 'RECENTLY_VIEWED_SERVERS')).fetch() as IGlobal[];
|
||||
const recentlyViewedServers = records?.[0]?.value;
|
||||
expect(recentlyViewedServers?.length).toBe(2);
|
||||
// new active server should change and we have a Database and is active
|
||||
activeServerUrl = await DatabaseManager.getActiveServerUrl();
|
||||
const serverB = await DatabaseManager.getActiveServerDatabase();
|
||||
expect(activeServerUrl).toBe(serverUrls[1]);
|
||||
expect(serverB).toEqual(DatabaseManager.serverDatabases[serverUrls[1]].database);
|
||||
});
|
||||
|
||||
it('=> should retrieve all database instances matching serverUrls parameter', async () => {
|
||||
expect.assertions(3);
|
||||
|
||||
await createTwoConnections();
|
||||
|
||||
const spyOnCreateDatabaseConnection = jest.spyOn(databaseManagerClient!, 'createDatabaseConnection');
|
||||
|
||||
const dbInstances = await databaseManagerClient!.retrieveDatabaseInstances([
|
||||
'https://xunity2.mattermost.com',
|
||||
'https://appv2.mattermost.com',
|
||||
'https://appv1.mattermost.com',
|
||||
]);
|
||||
|
||||
expect(dbInstances).toBeTruthy();
|
||||
const numDbInstances = dbInstances?.length ?? 0;
|
||||
|
||||
// The Database Manager will call the 'createDatabaseConnection' method in consequence of the number of database connection present in dbInstances array
|
||||
expect(spyOnCreateDatabaseConnection).toHaveBeenCalledTimes(numDbInstances);
|
||||
|
||||
// We should have two active database connection
|
||||
expect(numDbInstances).toEqual(2);
|
||||
});
|
||||
|
||||
it('=> should retrieve existing database instances matching serverUrl parameter', async () => {
|
||||
it('=> should delete appv1 server from the servers table of App database', async () => {
|
||||
expect.assertions(2);
|
||||
await createTwoConnections();
|
||||
const spyOnRetrieveDatabaseInstances = jest.spyOn(databaseManagerClient!, 'retrieveDatabaseInstances');
|
||||
const connection = await databaseManagerClient!.getDatabaseConnection({serverUrl: 'https://appv1.mattermost.com', setAsActiveDatabase: false});
|
||||
expect(spyOnRetrieveDatabaseInstances).toHaveBeenCalledTimes(1);
|
||||
expect(connection).toBeDefined();
|
||||
});
|
||||
|
||||
//todo: test the current active database together with the getDatabaseConnection method
|
||||
await DatabaseManager.setActiveServerDatabase('https://appv1.mattermost.com');
|
||||
await DatabaseManager.destroyServerDatabase('https://appv1.mattermost.com');
|
||||
|
||||
it('=> should have records of Servers set in the servers table of the default database', async () => {
|
||||
expect.assertions(3);
|
||||
|
||||
const defaultDB = await databaseManagerClient!.getDefaultDatabase();
|
||||
expect(defaultDB).toBeDefined();
|
||||
await createTwoConnections();
|
||||
const serversRecords = await defaultDB!.collections.get(SERVERS).query().fetch() as IServers[];
|
||||
expect(serversRecords).toBeDefined();
|
||||
|
||||
// We have call the 'DatabaseManager.setActiveServerDatabase' twice in the previous test case; that implies that we have 2 records in the 'servers' table
|
||||
expect(serversRecords.length).toEqual(2);
|
||||
});
|
||||
|
||||
it('=> should delete appv1 server from the servers table of Default database', async () => {
|
||||
expect.assertions(3);
|
||||
await createTwoConnections();
|
||||
|
||||
const defaultDatabase = await databaseManagerClient!.getDefaultDatabase();
|
||||
|
||||
await databaseManagerClient?.setActiveServerDatabase('https://appv1.mattermost.com');
|
||||
await databaseManagerClient?.setActiveServerDatabase('https://appv2.mattermost.com');
|
||||
|
||||
const fetchGlobalRecords = async () => {
|
||||
const initialGlobalRecords = await defaultDatabase!.collections.get(GLOBAL).query(Q.where('name', RECENTLY_VIEWED_SERVERS)).fetch() as IGlobal[];
|
||||
return initialGlobalRecords?.[0].value as string[];
|
||||
const fetchServerRecords = async (serverUrl: string) => {
|
||||
const servers = await DatabaseManager.appDatabase?.database!.collections.get(SERVERS).query(Q.where('url', serverUrl)).fetch() as IServers[];
|
||||
return servers.length;
|
||||
};
|
||||
|
||||
const recentServers = await fetchGlobalRecords();
|
||||
expect(recentServers.length).toBe(2);
|
||||
const destroyed = await fetchServerRecords(serverUrls[0]);
|
||||
expect(destroyed).toBe(0);
|
||||
|
||||
// Removing database for appv1 connection
|
||||
const isAppV1Removed = await databaseManagerClient!.deleteDatabase('https://appv1.mattermost.com');
|
||||
expect(isAppV1Removed).toBe(true);
|
||||
|
||||
// Verifying in the database to confirm if its record was deleted
|
||||
|
||||
const updatedRecentServers = await fetchGlobalRecords();
|
||||
expect(updatedRecentServers.length).toBe(1);
|
||||
});
|
||||
|
||||
it('=> should enforce uniqueness of connections using serverUrl as key', async () => {
|
||||
expect.assertions(2);
|
||||
|
||||
// We can't have more than one connection with the same server url
|
||||
const serverUrl = 'https://appv3.mattermost.com';
|
||||
await databaseManagerClient!.createDatabaseConnection({
|
||||
shouldAddToDefaultDatabase: true,
|
||||
configs: {
|
||||
actionsEnabled: true,
|
||||
dbName: 'community mattermost',
|
||||
dbType: DatabaseType.SERVER,
|
||||
serverUrl,
|
||||
},
|
||||
});
|
||||
|
||||
await databaseManagerClient!.createDatabaseConnection({
|
||||
shouldAddToDefaultDatabase: true,
|
||||
configs: {
|
||||
actionsEnabled: true,
|
||||
dbName: 'duplicate server',
|
||||
dbType: DatabaseType.SERVER,
|
||||
serverUrl,
|
||||
},
|
||||
});
|
||||
|
||||
const defaultDB = await databaseManagerClient!.getDefaultDatabase();
|
||||
|
||||
const allServers = defaultDB && await defaultDB.collections.get(SERVERS).query().fetch() as IServers[];
|
||||
|
||||
// We should be having some servers returned here
|
||||
expect(allServers?.length).toBeGreaterThan(0);
|
||||
|
||||
const occurrences = allServers?.map((server) => server.url).reduce((acc, cur) => (cur === serverUrl ? acc + 1 : acc), 0);
|
||||
|
||||
// We should only have one occurrence of the 'https://appv3.mattermost.com' url
|
||||
expect(occurrences).toEqual(1);
|
||||
const activeServerUrl = await DatabaseManager.getActiveServerUrl();
|
||||
expect(activeServerUrl).toEqual(serverUrls[1]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user