feat: MeteringService test fixes for now (#2050)

This commit is contained in:
Daniel Salazar
2025-11-26 15:09:30 -08:00
committed by GitHub
parent 6284b390b7
commit 93eddd2238
8 changed files with 83 additions and 23 deletions

View File

@@ -272,6 +272,7 @@ const config_pointer = {};
//
Object.defineProperty(context_config, 'strict', {
get: () => config_to_export.env === 'dev',
configurable: true,
});
module.exports = config_to_export;

View File

@@ -1,7 +1,7 @@
// Minimal EventService type declaration for MeteringService type safety
export interface EventService {
emit(key: string, data?: any, meta?: any): Promise<void>;
on(selector: string, callback: Function): { detach: () => void };
on_all(callback: Function): void;
get_scoped(scope: string): any;
export class EventService {
emit (key: string, data?: any, meta?: any): Promise<void>;
on (selector: string, callback: Function): { detach: () => void };
on_all (callback: Function): void;
get_scoped (scope: string): any;
}

View File

@@ -17,7 +17,6 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
const { Actor } = require('./auth/Actor');
const BaseService = require('./BaseService');
const { DB_READ } = require('./database/consts');
@@ -101,7 +100,7 @@ class GetUserService extends BaseService {
if ( cached && !options.force ) {
for ( const prop of this.id_properties ) {
if ( options.hasOwnProperty(prop) ) {
const user = kv.get(`users:${prop}:${options[prop]}`);
const user = globalThis.kv?.get(`users:${prop}:${options[prop]}`);
if ( user ) return user;
}
}
@@ -132,7 +131,7 @@ class GetUserService extends BaseService {
try {
for ( const prop of this.id_properties ) {
if ( user[prop] ) {
kv.set(`users:${prop}:${user[prop]}`, user);
globalThis.kv?.set(`users:${prop}:${user[prop]}`, user);
}
}
} catch ( e ) {

View File

@@ -1,15 +1,65 @@
import { describe, expect, it } from 'vitest';
import { createTestKernel } from '../../../tools/test.mjs';
import { MeteringServiceWrapper } from './MeteringServiceWrapper.mjs';
import { DBKVServiceWrapper } from '../repositories/DBKVStore/index.mjs';
import { SUService } from '../SUService';
import { AlarmService } from '../../modules/core/AlarmService';
import { EventService } from '../../services/EventService';
import { SqliteDatabaseAccessService } from '../database/SqliteDatabaseAccessService';
import { MeteringService } from './MeteringService';
import * as config from '../../config';
import { CommandService } from '../CommandService';
import { TraceService } from '../TraceService';
import { Actor } from '../auth/Actor';
import { GetUserService } from '../GetUserService';
import { DetailProviderService } from '../DetailProviderService';
describe('MeteringService', async () => {
const testKernel = await createTestKernel({
serviceMap: {
metering: MeteringServiceWrapper,
config.load_config({
'services': {
'database': {
path: ':memory:',
},
},
});
it('should have some services', () => {
expect(testKernel.services).not.toBeUndefined();
expect(testKernel.services!.get('metering')).toBeInstanceOf(MeteringServiceWrapper);
const testKernel = await createTestKernel({
serviceMap: {
'whoami': DetailProviderService,
'get-user': GetUserService,
database: SqliteDatabaseAccessService,
traceService: TraceService,
meteringService: MeteringServiceWrapper,
'puter-kvstore': DBKVServiceWrapper,
su: SUService,
alarm: AlarmService,
event: EventService,
commands: CommandService,
},
initLevelString: 'init',
});
await testKernel.services?.get('su').__on('boot.consolidation', []);
const testSubject = testKernel.services!.get('meteringService') as MeteringServiceWrapper;
it('should be instantiated', () => {
expect(testSubject).toBeInstanceOf(MeteringServiceWrapper);
});
it('should contain a copy of the public methods of meteringService too', () => {
// TODO DS: check all public MeteringService exist on the wrapper
});
it('should have meteringService instantiated', async () => {
expect(testSubject.meteringService).toBeInstanceOf(MeteringService);
});
it('should record usage for an actor', async () => {
const res = await testSubject.meteringService.incrementUsage({ type: { user: { uuid: 'test-user-id' } } } as unknown as Actor,
'aws-polly:standard:character',
1);
console.log(res);
expect(res).toBeDefined();
});
});

View File

@@ -18,7 +18,6 @@
*/
// METADATA // {"ai-commented":{"service":"openai-completion","model":"gpt-4o-mini"}}
const { get_user } = require('../helpers');
const { Context } = require('../util/context');
const { TeePromise } = require('@heyputer/putility').libs.promise;
const { Actor, UserActorType } = require('./auth/Actor');
@@ -56,7 +55,7 @@ class SUService extends BaseService {
* system user and actor have been set.
*/
async ['__on_boot.consolidation'] () {
const sys_user = await get_user({ username: 'system' });
const sys_user = await this.services.get('get-user').get_user({ username: 'system' });
this.sys_user_.resolve(sys_user);
const sys_actor = new Actor({
type: new UserActorType({

View File

@@ -1,6 +1,7 @@
import { SUB_POLICIES } from './MeteringService/subPolicies';
export interface IUser { uuid: string,
export interface IUser {
uuid: string,
username: string,
email: string,
subscription?: (typeof SUB_POLICIES)[number]['id'],

View File

@@ -43,11 +43,9 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService {
const require = this.require;
const Database = require('better-sqlite3');
this._register_commands(this.services.get('commands'));
const fs = require('fs');
const path_ = require('path');
const do_setup = !fs.existsSync(this.config.path);
const do_setup = this.config.path === ':memory:' || !fs.existsSync(this.config.path);
this.db = new Database(this.config.path);
@@ -185,7 +183,7 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService {
*/
const TARGET_VERSION = (() => {
const args = Context.get('args');
if ( args['database-target-version'] ) {
if ( args?.['database-target-version'] ) {
return parseInt(args['database-target-version']);
}
return HIGHEST_VERSION;
@@ -291,6 +289,10 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService {
});
}
async '__on_boot.consolidation' () {
this._register_commands(this.services.get('commands'));
}
/**
* Implementation for prepared statements for READ operations.
*/

View File

@@ -105,6 +105,7 @@ export class TestKernel extends AdvancedBase {
services,
useapi: this.useapi,
['runtime-modules']: this.runtimeModuleRegistry,
args: {},
}, 'app');
this.root_context = root_context;
globalThis.root_context = root_context;
@@ -274,7 +275,8 @@ export const createTestKernel = async ({
serviceMap,
initLevelString = 'construct',
}) => {
const initLevelMap = { CONSTRUCT: 1 };
const initLevelMap = { CONSTRUCT: 1, INIT: 2 };
const initLevel = initLevelMap[(`${initLevelString}`).toUpperCase()];
const testKernel = new TestKernel();
testKernel.add_module(new Core2Module());
@@ -297,5 +299,11 @@ export const createTestKernel = async ({
await ins.construct();
}
}
for ( const name of service_names ) {
const ins = testKernel.services.instances_[name];
if ( initLevel >= initLevelMap.INIT ) {
await ins.init();
}
}
return testKernel;
};