/*
* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
import {
SurfaceController,
SurfaceErrorType,
SurfaceEventType,
ActionReceiver,
ErrorCallback,
SurfaceEventCallback
} from '../main/ets/engine/core/SurfaceController';
import { Catalog } from '../main/ets/engine/core/Catalog';
import { A2UIMessageType } from '../main/ets/engine/core/A2UIMessage';
export default function SurfaceControllerUnitTest() {
describe('SurfaceControllerTest', () => {
describe('Constructor', () => {
it('should_create_controller_with_catalog_and_callback', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let controller = new SurfaceController(catalog, eventCallback);
expect(controller !== null).assertTrue();
expect(controller !== undefined).assertTrue();
});
it('should_create_controller_with_schema_check_enabled', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let controller = new SurfaceController(catalog, eventCallback, true);
expect(controller !== null).assertTrue();
});
it('should_create_controller_with_schema_check_disabled', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let controller = new SurfaceController(catalog, eventCallback, false);
expect(controller !== null).assertTrue();
});
it('should_create_controller_with_catalog_id', 0, () => {
let catalog = new Catalog('https://example.com/catalog.json', []);
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let controller = new SurfaceController(catalog, eventCallback);
expect(controller !== null).assertTrue();
});
});
describe('RegisterActionReceiver', () => {
it('should_register_action_receiver_successfully', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let controller = new SurfaceController(catalog, eventCallback);
let actionReceiver: ActionReceiver = (action: string) => {};
controller.registerActionReceiver(actionReceiver);
});
it('should_register_different_action_receivers', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let controller = new SurfaceController(catalog, eventCallback);
let receiver1: ActionReceiver = (action: string) => {};
let receiver2: ActionReceiver = (action: string) => {};
controller.registerActionReceiver(receiver1);
controller.registerActionReceiver(receiver2);
});
});
describe('RegisterErrorCallback', () => {
it('should_register_error_callback_successfully', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let controller = new SurfaceController(catalog, eventCallback);
let errorCallback: ErrorCallback = (code, errorMsg) => {};
controller.registerErrorCallback(errorCallback);
});
it('should_register_different_error_callbacks', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let controller = new SurfaceController(catalog, eventCallback);
let callback1: ErrorCallback = (code, errorMsg) => {};
let callback2: ErrorCallback = (code, errorMsg) => {};
controller.registerErrorCallback(callback1);
controller.registerErrorCallback(callback2);
});
});
describe('EventNotification', () => {
it('should_notify_surface_created_event', 0, () => {
let catalog = Catalog.basic();
let receivedEventType: SurfaceEventType = SurfaceEventType.UNKNOWN;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {
receivedEventType = eventType;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback((code, msg) => {});
let dsl = '{"version":"v0.9","createSurface":{"surfaceId":"main","catalogId":"catalog"}}';
controller.onReceive(dsl);
expect(receivedEventType).assertEqual(SurfaceEventType.SURFACE_CREATED);
});
it('should_notify_surface_components_updated_event', 0, () => {
let catalog = Catalog.basic();
let receivedEventType: SurfaceEventType = SurfaceEventType.UNKNOWN;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {
receivedEventType = eventType;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback((code, msg) => {});
let dsl = '{"version":"v0.9","updateComponents":{"surfaceId":"main","components":[]}}';
controller.onReceive(dsl);
expect(receivedEventType).assertEqual(SurfaceEventType.SURFACE_COMPONENTS_UPDATED);
});
it('should_notify_surface_data_model_updated_event', 0, () => {
let catalog = Catalog.basic();
let receivedEventType: SurfaceEventType = SurfaceEventType.UNKNOWN;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {
receivedEventType = eventType;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback((code, msg) => {});
let dsl = '{"version":"v0.9","updateDataModel":{"surfaceId":"main","value":{}}}';
controller.onReceive(dsl);
expect(receivedEventType).assertEqual(SurfaceEventType.SURFACE_DATA_MODEL_UPDATED);
});
it('should_notify_surface_deleted_event', 0, () => {
let catalog = Catalog.basic();
let receivedEventType: SurfaceEventType = SurfaceEventType.UNKNOWN;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {
receivedEventType = eventType;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback((code, msg) => {});
let dsl = '{"version":"v0.9","deleteSurface":{"surfaceId":"main"}}';
controller.onReceive(dsl);
expect(receivedEventType).assertEqual(SurfaceEventType.SURFACE_DELETED);
});
it('should_not_notify_event_when_callback_is_undefined', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = undefined as any;
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback((code, msg) => {});
let dsl = '{"version":"v0.9","createSurface":{"surfaceId":"main"}}';
controller.onReceive(dsl);
});
});
describe('ErrorHandling', () => {
it('should_call_error_callback_when_invalid_json', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let receivedErrorCode: SurfaceErrorType = SurfaceErrorType.NO_ERROR;
let receivedErrorMsg: string = '';
let errorCallback: ErrorCallback = (code, errorMsg) => {
receivedErrorCode = code;
receivedErrorMsg = errorMsg;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback(errorCallback);
controller.onReceive('invalid json');
expect(receivedErrorCode).assertEqual(SurfaceErrorType.ERROR_NO_SURFACE_MATCHED);
expect(receivedErrorMsg).assertEqual('dsl message parse failed');
});
it('should_call_error_callback_when_empty_string', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let receivedErrorCode: SurfaceErrorType = SurfaceErrorType.NO_ERROR;
let errorCallback: ErrorCallback = (code, errorMsg) => {
receivedErrorCode = code;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback(errorCallback);
controller.onReceive('');
expect(receivedErrorCode).assertEqual(SurfaceErrorType.ERROR_NO_SURFACE_MATCHED);
});
it('should_call_error_callback_when_missing_version', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let receivedErrorCode: SurfaceErrorType = SurfaceErrorType.NO_ERROR;
let errorCallback: ErrorCallback = (code, errorMsg) => {
receivedErrorCode = code;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback(errorCallback);
let dsl = '{"createSurface":{"surfaceId":"main"}}';
controller.onReceive(dsl);
expect(receivedErrorCode).assertEqual(SurfaceErrorType.ERROR_NO_SURFACE_MATCHED);
});
it('should_call_error_callback_when_unknown_message_type', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let receivedErrorCode: SurfaceErrorType = SurfaceErrorType.NO_ERROR;
let errorCallback: ErrorCallback = (code, errorMsg) => {
receivedErrorCode = code;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback(errorCallback);
let dsl = '{"version":"v0.9","unknownType":{"surfaceId":"main"}}';
controller.onReceive(dsl);
expect(receivedErrorCode).assertEqual(SurfaceErrorType.ERROR_NO_SURFACE_MATCHED);
});
it('should_call_error_callback_when_missing_surfaceId', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let receivedErrorCode: SurfaceErrorType = SurfaceErrorType.NO_ERROR;
let errorCallback: ErrorCallback = (code, errorMsg) => {
receivedErrorCode = code;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback(errorCallback);
let dsl = '{"version":"v0.9","createSurface":{}}';
controller.onReceive(dsl);
expect(receivedErrorCode).assertEqual(SurfaceErrorType.ERROR_NO_SURFACE_MATCHED);
});
it('should_not_call_error_callback_when_no_error_callback_registered', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let controller = new SurfaceController(catalog, eventCallback);
controller.onReceive('invalid json');
});
});
describe('OnReceive', () => {
it('should_handle_create_surface_message', 0, () => {
let catalog = Catalog.basic();
let receivedEventType: SurfaceEventType = SurfaceEventType.UNKNOWN;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {
receivedEventType = eventType;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback((code, msg) => {});
let dsl = '{"version":"v0.9","createSurface":{"surfaceId":"test-surface","catalogId":"test-catalog"}}';
controller.onReceive(dsl);
expect(receivedEventType).assertEqual(SurfaceEventType.SURFACE_CREATED);
});
it('should_handle_update_components_message', 0, () => {
let catalog = Catalog.basic();
let receivedEventType: SurfaceEventType = SurfaceEventType.UNKNOWN;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {
receivedEventType = eventType;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback((code, msg) => {});
let dsl = '{"version":"v0.9","updateComponents":{"surfaceId":"main","components":[{"id":"text1","component":"Text","text":"Hello"}]}}';
controller.onReceive(dsl);
expect(receivedEventType).assertEqual(SurfaceEventType.SURFACE_COMPONENTS_UPDATED);
});
it('should_handle_update_data_model_message', 0, () => {
let catalog = Catalog.basic();
let receivedEventType: SurfaceEventType = SurfaceEventType.UNKNOWN;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {
receivedEventType = eventType;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback((code, msg) => {});
let dsl = '{"version":"v0.9","updateDataModel":{"surfaceId":"main","value":{"count":42}}}';
controller.onReceive(dsl);
expect(receivedEventType).assertEqual(SurfaceEventType.SURFACE_DATA_MODEL_UPDATED);
});
it('should_handle_delete_surface_message', 0, () => {
let catalog = Catalog.basic();
let receivedEventType: SurfaceEventType = SurfaceEventType.UNKNOWN;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {
receivedEventType = eventType;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback((code, msg) => {});
let dsl = '{"version":"v0.9","deleteSurface":{"surfaceId":"main"}}';
controller.onReceive(dsl);
expect(receivedEventType).assertEqual(SurfaceEventType.SURFACE_DELETED);
});
it('should_handle_multiple_sequential_messages', 0, () => {
let catalog = Catalog.basic();
let eventTypes: SurfaceEventType[] = [];
let eventCallback: SurfaceEventCallback = (eventType, controller) => {
eventTypes.push(eventType);
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback((code, msg) => {});
controller.onReceive('{"version":"v0.9","createSurface":{"surfaceId":"main"}}');
controller.onReceive('{"version":"v0.9","updateComponents":{"surfaceId":"main","components":[]}}');
controller.onReceive('{"version":"v0.9","updateDataModel":{"surfaceId":"main","value":{}}}');
controller.onReceive('{"version":"v0.9","deleteSurface":{"surfaceId":"main"}}');
expect(eventTypes.length).assertEqual(4);
expect(eventTypes[0]).assertEqual(SurfaceEventType.SURFACE_CREATED);
expect(eventTypes[1]).assertEqual(SurfaceEventType.SURFACE_COMPONENTS_UPDATED);
expect(eventTypes[2]).assertEqual(SurfaceEventType.SURFACE_DATA_MODEL_UPDATED);
expect(eventTypes[3]).assertEqual(SurfaceEventType.SURFACE_DELETED);
});
it('should_handle_json_with_whitespace', 0, () => {
let catalog = Catalog.basic();
let receivedEventType: SurfaceEventType = SurfaceEventType.UNKNOWN;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {
receivedEventType = eventType;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback((code, msg) => {});
let dsl = '{ "version" : "v0.9" , "createSurface" : { "surfaceId" : "main" } }';
controller.onReceive(dsl);
expect(receivedEventType).assertEqual(SurfaceEventType.SURFACE_CREATED);
});
});
describe('SurfaceErrorTypeEnum', () => {
it('should_have_correct_error_type_values', 0, () => {
expect(SurfaceErrorType.NO_ERROR).assertEqual(0);
expect(SurfaceErrorType.ERROR_NO_SURFACE_MATCHED).assertEqual(1);
});
});
describe('SurfaceEventTypeEnum', () => {
it('should_have_correct_event_type_values', 0, () => {
expect(SurfaceEventType.UNKNOWN).assertEqual(-1);
expect(SurfaceEventType.SURFACE_CREATED).assertEqual(0);
expect(SurfaceEventType.SURFACE_COMPONENTS_UPDATED).assertEqual(1);
expect(SurfaceEventType.SURFACE_DATA_MODEL_UPDATED).assertEqual(2);
expect(SurfaceEventType.SURFACE_DELETED).assertEqual(3);
});
});
describe('EdgeCases', () => {
it('should_handle_null_json', 0, () => {
let catalog = Catalog.basic();
let receivedErrorCode: SurfaceErrorType = SurfaceErrorType.NO_ERROR;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let errorCallback: ErrorCallback = (code, errorMsg) => {
receivedErrorCode = code;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback(errorCallback);
controller.onReceive('null');
expect(receivedErrorCode).assertEqual(SurfaceErrorType.ERROR_NO_SURFACE_MATCHED);
});
it('should_handle_json_array', 0, () => {
let catalog = Catalog.basic();
let receivedErrorCode: SurfaceErrorType = SurfaceErrorType.NO_ERROR;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let errorCallback: ErrorCallback = (code, errorMsg) => {
receivedErrorCode = code;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback(errorCallback);
controller.onReceive('[]');
expect(receivedErrorCode).assertEqual(SurfaceErrorType.ERROR_NO_SURFACE_MATCHED);
});
it('should_handle_empty_json_object', 0, () => {
let catalog = Catalog.basic();
let receivedErrorCode: SurfaceErrorType = SurfaceErrorType.NO_ERROR;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let errorCallback: ErrorCallback = (code, errorMsg) => {
receivedErrorCode = code;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback(errorCallback);
controller.onReceive('{}');
expect(receivedErrorCode).assertEqual(SurfaceErrorType.ERROR_NO_SURFACE_MATCHED);
});
it('should_handle_whitespace_only_string', 0, () => {
let catalog = Catalog.basic();
let receivedErrorCode: SurfaceErrorType = SurfaceErrorType.NO_ERROR;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let errorCallback: ErrorCallback = (code, errorMsg) => {
receivedErrorCode = code;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback(errorCallback);
controller.onReceive(' ');
expect(receivedErrorCode).assertEqual(SurfaceErrorType.ERROR_NO_SURFACE_MATCHED);
});
it('should_handle_unclosed_json_object', 0, () => {
let catalog = Catalog.basic();
let receivedErrorCode: SurfaceErrorType = SurfaceErrorType.NO_ERROR;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let errorCallback: ErrorCallback = (code, errorMsg) => {
receivedErrorCode = code;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback(errorCallback);
controller.onReceive('{"version":"v0.9"');
expect(receivedErrorCode).assertEqual(SurfaceErrorType.ERROR_NO_SURFACE_MATCHED);
});
it('should_handle_version_null', 0, () => {
let catalog = Catalog.basic();
let receivedErrorCode: SurfaceErrorType = SurfaceErrorType.NO_ERROR;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let errorCallback: ErrorCallback = (code, errorMsg) => {
receivedErrorCode = code;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback(errorCallback);
let dsl = '{"version":null,"createSurface":{"surfaceId":"main"}}';
controller.onReceive(dsl);
expect(receivedErrorCode).assertEqual(SurfaceErrorType.ERROR_NO_SURFACE_MATCHED);
});
it('should_handle_special_characters_in_surfaceId', 0, () => {
let catalog = Catalog.basic();
let receivedEventType: SurfaceEventType = SurfaceEventType.UNKNOWN;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {
receivedEventType = eventType;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback((code, msg) => {});
let dsl = '{"version":"v0.9","createSurface":{"surfaceId":"test-surface_123"}}';
controller.onReceive(dsl);
expect(receivedEventType).assertEqual(SurfaceEventType.SURFACE_CREATED);
});
it('should_handle_unicode_in_surfaceId', 0, () => {
let catalog = Catalog.basic();
let receivedEventType: SurfaceEventType = SurfaceEventType.UNKNOWN;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {
receivedEventType = eventType;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback((code, msg) => {});
let dsl = '{"version":"v0.9","createSurface":{"surfaceId":"主界面"}}';
controller.onReceive(dsl);
expect(receivedEventType).assertEqual(SurfaceEventType.SURFACE_CREATED);
});
});
describe('CallbackValidation', () => {
it('should_pass_correct_controller_instance_in_event_callback', 0, () => {
let catalog = Catalog.basic();
let receivedController: SurfaceController | null = null;
let eventCallback: SurfaceEventCallback = (eventType, controller) => {
receivedController = controller;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback((code, msg) => {});
let dsl = '{"version":"v0.9","createSurface":{"surfaceId":"main"}}';
controller.onReceive(dsl);
expect(receivedController !== null).assertTrue();
expect(receivedController === controller).assertTrue();
});
it('should_receive_correct_error_code_type', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let receivedCode: SurfaceErrorType | null = null;
let errorCallback: ErrorCallback = (code, errorMsg) => {
receivedCode = code;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback(errorCallback);
controller.onReceive('invalid json');
expect(receivedCode !== null).assertTrue();
expect(typeof receivedCode).assertEqual('number');
});
it('should_receive_correct_error_message_type', 0, () => {
let catalog = Catalog.basic();
let eventCallback: SurfaceEventCallback = (eventType, controller) => {};
let receivedMsg: string | null = null;
let errorCallback: ErrorCallback = (code, errorMsg) => {
receivedMsg = errorMsg;
};
let controller = new SurfaceController(catalog, eventCallback);
controller.registerErrorCallback(errorCallback);
controller.onReceive('invalid json');
expect(receivedMsg !== null).assertTrue();
expect(typeof receivedMsg).assertEqual('string');
});
});
});
}