### Install ComponentFramework Mock with yarn
Source: https://github.com/shko-online/componentframework-mock/blob/main/README.md
Installs the ComponentFramework Mock package as a development dependency using yarn.
```cmd
yarn add -D @shko.online/componentframework-mock
```
--------------------------------
### Install ComponentFramework Mock with npm
Source: https://github.com/shko-online/componentframework-mock/blob/main/README.md
Installs the ComponentFramework Mock package as a development dependency using npm.
```cmd
npm install -D @shko.online/componentframework-mock
```
--------------------------------
### CSS Styling Import and Application
Source: https://github.com/shko-online/componentframework-mock/blob/main/storybook/stories/Introduction.mdx
Imports and applies CSS styles to the Introduction component. It uses a CSS module for scoped styling.
```javascript
import style from './Introduction.style.css';
```
--------------------------------
### Storybook Metadata Configuration
Source: https://github.com/shko-online/componentframework-mock/blob/main/storybook/stories/Introduction.mdx
Configures the Storybook metadata for the Introduction component. It sets the title for the component within the Storybook UI.
```javascript
import { Meta } from '@storybook/blocks';
```
--------------------------------
### Initialize and Test Property Mocks with ComponentFrameworkMockGenerator
Source: https://context7.com/shko-online/componentframework-mock/llms.txt
Demonstrates how to initialize and test various property mocks (DateTime, Enum, Lookup, String, WholeNumber, OptionSet, MultiSelectOptionSet) using the ComponentFrameworkMockGenerator. It covers setting initial values, reading raw property data, and simulating platform updates.
```typescript
import {
ComponentFrameworkMockGenerator,
DateTimePropertyMock,
EnumPropertyMock,
LookupPropertyMock,
StringPropertyMock,
WholeNumberPropertyMock,
OptionSetPropertyMock,
MultiSelectOptionSetPropertyMock,
} from '@shko.online/componentframework-mock';
import { MyControl } from './MyControl';
import { IInputs, IOutputs } from './MyControl/generated/ManifestTypes';
describe('Property Mocks', () => {
let mockGenerator: ComponentFrameworkMockGenerator;
beforeEach(() => {
const container = document.createElement('div');
mockGenerator = new ComponentFrameworkMockGenerator(
MyControl,
{
dateField: DateTimePropertyMock,
enumField: EnumPropertyMock,
lookupField: LookupPropertyMock,
textField: StringPropertyMock,
numberField: WholeNumberPropertyMock,
statusField: OptionSetPropertyMock,
tagsField: MultiSelectOptionSetPropertyMock,
},
container,
);
// Set initial values
mockGenerator.context._SetCanvasItems({
dateField: new Date(2023, 5, 15),
enumField: 'Yes',
lookupField: { entityType: 'contact', id: 'contact-1', name: 'John Doe' },
textField: 'Hello World',
numberField: 42,
statusField: 1,
tagsField: [1, 2, 3],
});
});
it('Should read property values', () => {
mockGenerator.ExecuteInit();
mockGenerator.ExecuteUpdateView();
expect(mockGenerator.context._parameters.dateField.raw).toEqual(new Date(2023, 5, 15));
expect(mockGenerator.context._parameters.enumField.raw).toEqual('Yes');
expect(mockGenerator.context._parameters.lookupField.raw[0].name).toEqual('John Doe');
expect(mockGenerator.context._parameters.textField.raw).toEqual('Hello World');
expect(mockGenerator.context._parameters.numberField.raw).toEqual(42);
});
it('Should update property values from platform', () => {
mockGenerator.ExecuteInit();
mockGenerator.ExecuteUpdateView();
// Simulate platform updating values
mockGenerator.context._parameters.dateField._SetValue(new Date(2024, 0, 1));
mockGenerator.context._parameters.dateField._Refresh();
expect(mockGenerator.context._parameters.dateField.raw).toEqual(new Date(2024, 0, 1));
});
it('Should use UpdateValues for bulk updates', () => {
mockGenerator.ExecuteInit();
mockGenerator.ExecuteUpdateView();
// Update multiple values at once (simulates platform changes)
mockGenerator.UpdateValues({
textField: 'Updated Text',
numberField: 100,
enumField: 'No',
});
mockGenerator.ExecuteUpdateView();
expect(mockGenerator.context.updatedProperties).toContain('textField');
expect(mockGenerator.context.updatedProperties).toContain('numberField');
expect(mockGenerator.context.updatedProperties).toContain('enumField');
});
});
```
--------------------------------
### Import PCF Component and Types
Source: https://github.com/shko-online/componentframework-mock/blob/main/README.md
Imports a sample PCF component (OwnerLookup) and its associated input/output types for use in tests or stories.
```typescript
import { OwnerLookup } from '../__sample-components__/OwnerLookup';
import { IInputs, IOutputs } from '../__sample-components__/OwnerLookup/generated/ManifestTypes';
```
--------------------------------
### Initialize and Test DataSetMock with TypeScript
Source: https://context7.com/shko-online/componentframework-mock/llms.txt
Demonstrates initializing the DataSetMock with records using `_InitItems` and testing standard DataSet API methods like `sortedRecordIds`, `columns`, `records`, `paging`, and `filtering` within a TypeScript test environment. It also includes tests for record selection and clearing selections.
```typescript
import { ComponentFrameworkMockGenerator, DataSetMock } from '@shko.online/componentframework-mock';
import { GridControl } from './GridControl';
import { IInputs, IOutputs } from './GridControl/generated/ManifestTypes';
describe('GridControl', () => {
let mockGenerator: ComponentFrameworkMockGenerator;
beforeEach(() => {
const container = document.createElement('div');
mockGenerator = new ComponentFrameworkMockGenerator(
GridControl,
{
records: DataSetMock,
},
container,
);
// Initialize dataset with records
mockGenerator.context._parameters.records._InitItems([
{ id: '1', name: 'Betim', company: 'Shko Online' },
{ id: '2', name: 'John', company: 'AlbanianXrm' },
]);
document.body.appendChild(container);
});
it('Should render data grid', (done) => {
// Listen for dataset loaded callback
mockGenerator.context._parameters.records._onLoaded.callsFake(() => {
expect(mockGenerator.container).toMatchSnapshot();
// Verify dataset properties
expect(mockGenerator.context._parameters.records.sortedRecordIds).toEqual(['1', '2']);
expect(mockGenerator.context._parameters.records.columns.length).toBe(3);
done();
});
mockGenerator.ExecuteInit();
mockGenerator.ExecuteUpdateView();
});
it('Should handle record selection', () => {
mockGenerator.ExecuteInit();
const dataset = mockGenerator.context._parameters.records;
dataset.setSelectedRecordIds(['1', '2']);
expect(dataset.getSelectedRecordIds()).toEqual(['1', '2']);
dataset.clearSelectedRecordIds();
expect(dataset.getSelectedRecordIds()).toEqual([]);
});
});
```
--------------------------------
### Instantiate ComponentFrameworkMockGenerator
Source: https://github.com/shko-online/componentframework-mock/blob/main/README.md
Creates an instance of ComponentFrameworkMockGenerator, providing the component, parameter mappings, and a container element.
```typescript
let mockGenerator: ComponentFrameworkMockGenerator = new ComponentFrameworkMockGenerator(
OwnerLookup,
{
value: LookupPropertyMock,
},
container,
);
```
--------------------------------
### Execute Component Lifecycle Methods
Source: https://github.com/shko-online/componentframework-mock/blob/main/README.md
Executes the initialization and update view methods for the mock component. ExecuteInit should be called once, and ExecuteUpdateView at least once.
```typescript
mockGenerator.ExecuteInit();
mockGenerator.ExecuteUpdateView();
```
--------------------------------
### Mock PCF Navigation API with Sinon Stubs (TypeScript)
Source: https://context7.com/shko-online/componentframework-mock/llms.txt
This snippet demonstrates how to mock the PCF Navigation API using Sinon stubs within a TypeScript test environment. It covers mocking alert dialogs, confirm dialogs with custom responses, form navigation, and tracking URL navigation calls. The mockGenerator from @shko.online/componentframework-mock is used to set up and interact with these mocked navigation methods.
```typescript
import { ComponentFrameworkMockGenerator, StringPropertyMock } from '@shko.online/componentframework-mock';
import { MyControl } from './MyControl';
import { IInputs, IOutputs } from './MyControl/generated/ManifestTypes';
describe('NavigationMock', () => {
let mockGenerator: ComponentFrameworkMockGenerator;
beforeEach(() => {
const container = document.createElement('div');
mockGenerator = new ComponentFrameworkMockGenerator(
MyControl,
{ textField: StringPropertyMock },
container,
);
});
it('Should mock alert dialogs', async () => {
mockGenerator.ExecuteInit();
await mockGenerator.context.navigation.openAlertDialog({
text: 'This is an alert',
confirmButtonLabel: 'OK',
});
expect(mockGenerator.context.navigation.openAlertDialog.calledOnce).toBeTruthy();
});
it('Should mock confirm dialogs with custom response', async () => {
// Configure custom response
mockGenerator.context.navigation.openConfirmDialog.resolves({ confirmed: false });
mockGenerator.ExecuteInit();
const result = await mockGenerator.context.navigation.openConfirmDialog({
title: 'Confirm Action',
text: 'Are you sure?',
});
expect(result.confirmed).toBe(false);
});
it('Should mock form navigation', async () => {
mockGenerator.context.navigation.openForm.resolves({
savedEntityReference: [{ entityType: 'account', id: 'new-id', name: 'New Account' }],
});
mockGenerator.ExecuteInit();
const result = await mockGenerator.context.navigation.openForm({
entityName: 'account',
useQuickCreateForm: true,
});
expect(result.savedEntityReference[0].entityType).toEqual('account');
});
it('Should track URL navigation', () => {
mockGenerator.ExecuteInit();
mockGenerator.context.navigation.openUrl('https://example.com', { height: 600, width: 800 });
expect(mockGenerator.context.navigation.openUrl.calledWith('https://example.com')).toBeTruthy();
});
});
```
--------------------------------
### Test PCF Control Mode and Context Properties with TypeScript
Source: https://context7.com/shko-online/componentframework-mock/llms.txt
This TypeScript code demonstrates how to use the ComponentFrameworkMockGenerator to test various mode and context properties of a PCF control. It covers setting visibility, disabled states, fullscreen mode, tracking container resize, and accessing user settings. Dependencies include @shko.online/componentframework-mock and the control's generated manifest types.
```typescript
import { ComponentFrameworkMockGenerator, LookupPropertyMock } from '@shko.online/componentframework-mock';
import { MyControl } from './MyControl';
import { IInputs, IOutputs } from './MyControl/generated/ManifestTypes';
describe('Mode and Context', () => {
let mockGenerator: ComponentFrameworkMockGenerator;
beforeEach(() => {
const container = document.createElement('div');
mockGenerator = new ComponentFrameworkMockGenerator(
MyControl,
{ value: LookupPropertyMock },
container,
);
});
it('Should handle visibility and disabled states', () => {
mockGenerator.context.mode.isVisible = true;
mockGenerator.context.mode.isControlDisabled = false;
mockGenerator.ExecuteInit();
mockGenerator.ExecuteUpdateView();
// Toggle disabled state
mockGenerator.context.mode.isControlDisabled = true;
mockGenerator.ExecuteUpdateView();
expect(mockGenerator.control.updateView.calledTwice).toBeTruthy();
});
it('Should handle fullscreen mode', () => {
mockGenerator.ExecuteInit();
mockGenerator.context.mode.setFullScreen(true);
expect(mockGenerator.context.updatedProperties).toContain('fullscreen_open');
mockGenerator.context.mode._FullScreen = true;
mockGenerator.context.mode.setFullScreen(false);
expect(mockGenerator.context.updatedProperties).toContain('fullscreen_close');
});
it('Should track container resize', () => {
mockGenerator.ExecuteInit();
// Enable resize tracking
mockGenerator.context.mode.trackContainerResize(true);
// Access allocated dimensions
mockGenerator.context.mode.allocatedHeight = 400;
mockGenerator.context.mode.allocatedWidth = 600;
mockGenerator.ExecuteUpdateView();
});
it('Should configure user settings', () => {
mockGenerator.context.userSettings.userId = 'user-guid';
mockGenerator.context.userSettings.userName = 'Test User';
mockGenerator.context.userSettings.languageId = 1033; // English
mockGenerator.ExecuteInit();
// User settings are available to the control
expect(mockGenerator.context.userSettings.userId).toEqual('user-guid');
});
});
```
--------------------------------
### Test React PCF Controls with ComponentFrameworkMockGeneratorReact
Source: https://context7.com/shko-online/componentframework-mock/llms.txt
Tests virtual/React-based PCF controls using ComponentFrameworkMockGeneratorReact. Initializes the mock environment, sets property values, and simulates the PCF lifecycle to render ReactElements. Suitable for controls implementing ComponentFramework.ReactControl.
```typescript
import { ComponentFrameworkMockGeneratorReact, StringPropertyMock } from '@shko.online/componentframework-mock';
import { render } from 'react-test-renderer';
import { MyReactControl } from './MyReactControl';
import { IInputs, IOutputs } from './MyReactControl/generated/ManifestTypes';
describe('MyReactControl', () => {
let mockGenerator: ComponentFrameworkMockGeneratorReact;
beforeEach(() => {
mockGenerator = new ComponentFrameworkMockGeneratorReact(
MyReactControl,
{
textValue: StringPropertyMock,
},
);
mockGenerator.context._SetCanvasItems({
textValue: 'Hello World',
});
});
it('Should render React component', () => {
mockGenerator.ExecuteInit();
// ExecuteUpdateView returns a ReactElement for virtual controls
const reactElement = mockGenerator.ExecuteUpdateView();
const tree = render(reactElement);
expect(tree.toJSON()).toMatchSnapshot();
});
});
```
--------------------------------
### Orchestrate Multiple PCF Controls with Shared State
Source: https://context7.com/shko-online/componentframework-mock/llms.txt
Demonstrates how to use ComponentFrameworkMockOrchestrator to test multiple PCF controls that share state or interact. It creates a shared MetadataDB instance, allowing controls to access and coordinate updates to entity data. This is useful for scenarios involving complex inter-component communication.
```typescript
import {
ComponentFrameworkMockOrchestrator,
DateTimePropertyMock,
EnumPropertyMock,
LookupPropertyMock,
} from '@shko.online/componentframework-mock';
import { OwnerLookup } from './OwnerLookup';
import { YearPicker } from './YearPicker';
import { IInputs as IInputs1, IOutputs as IOutputs1 } from './OwnerLookup/generated/ManifestTypes';
import { IInputs as IInputs2, IOutputs as IOutputs2 } from './YearPicker/generated/ManifestTypes';
describe('Multiple Components', () => {
let orchestrator: ComponentFrameworkMockOrchestrator<[IInputs1, IOutputs1, false, IInputs2, IOutputs2, false]>;
beforeEach(() => {
const container1 = document.createElement('div');
const container2 = document.createElement('div');
orchestrator = new ComponentFrameworkMockOrchestrator([
[OwnerLookup, { value: LookupPropertyMock }, container1],
[YearPicker, { value: DateTimePropertyMock, enum: EnumPropertyMock }, container2],
]);
// Configure first control
orchestrator.mockGenerators[0].context._SetCanvasItems({
value: { entityType: 'team', id: 'guid1', name: 'Shko Online' },
});
// Configure second control
orchestrator.mockGenerators[1].context._SetCanvasItems({
value: new Date(2023, 0, 1),
enum: 'Yes',
});
document.body.appendChild(container1);
document.body.appendChild(container2);
});
it('Should initialize and update both controls', () => {
// Initialize all controls at once
orchestrator.ExecuteInit();
// Update views individually
orchestrator.mockGenerators[0].ExecuteUpdateView();
orchestrator.mockGenerators[1].ExecuteUpdateView();
expect(document.body).toMatchSnapshot();
});
it('Should share database between controls', () => {
orchestrator.ExecuteInit();
// Both controls share the same MetadataDB
const sharedDb = orchestrator.db;
// Add data that both controls can access
sharedDb.initMetadata([
{
LogicalName: 'contact',
EntitySetName: 'contacts',
PrimaryIdAttribute: 'contactid',
PrimaryNameAttribute: 'fullname',
Attributes: [],
},
]);
sharedDb.initItems({
'@odata.context': '#contacts',
value: [{ contactid: 'c1', fullname: 'Test Contact' }],
});
// Both controls can now query this data via context.webAPI
});
});
```
--------------------------------
### WebAPI Mock Testing with TypeScript
Source: https://context7.com/shko-online/componentframework-mock/llms.txt
Demonstrates testing CRUD operations against a mocked Dataverse WebAPI using TypeScript. It initializes metadata, populates test data, and performs create, retrieve, update, and delete operations.
```typescript
import { ComponentFrameworkMockGenerator, StringPropertyMock, AttributeType, ShkoOnline } from '@shko.online/componentframework-mock';
import { WebAPIControl } from './WebAPIControl';
import { IInputs, IOutputs } from './WebAPIControl/generated/ManifestTypes';
describe('WebAPIControl', () => {
let mockGenerator: ComponentFrameworkMockGenerator;
beforeEach(() => {
const container = document.createElement('div');
mockGenerator = new ComponentFrameworkMockGenerator(
WebAPIControl,
{ stringProperty: StringPropertyMock },
container,
);
// Initialize entity metadata
mockGenerator.metadata.initMetadata([
{
LogicalName: 'account',
EntitySetName: 'accounts',
PrimaryIdAttribute: 'accountid',
PrimaryNameAttribute: 'name',
Attributes: [
{ AttributeType: AttributeType.Uniqueidentifier, LogicalName: 'accountid', SchemaName: 'AccountId' } as ShkoOnline.AttributeMetadata,
{ AttributeType: AttributeType.String, LogicalName: 'name', SchemaName: 'Name' } as ShkoOnline.StringAttributeMetadata,
{ AttributeType: AttributeType.Money, LogicalName: 'revenue', SchemaName: 'Revenue' } as ShkoOnline.AttributeMetadata,
],
},
]);
// Optional: Set WebAPI delay to 0 for faster tests
mockGenerator.context.webAPI._Delay = 0;
});
it('Should create and retrieve records', async () => {
// Create a record
const created = await mockGenerator.context.webAPI.createRecord('account', {
name: 'Contoso',
revenue: 1000000,
});
expect(created.id).toBeDefined();
// Retrieve the record
const retrieved = await mockGenerator.context.webAPI.retrieveRecord('account', created.id);
expect(retrieved.name).toEqual('Contoso');
});
it('Should retrieve multiple records with FetchXML', async () => {
// Add test data
mockGenerator.metadata.initItems({
'@odata.context': '#accounts',
value: [
{ accountid: 'id-1', name: 'Account A', revenue: 500000 },
{ accountid: 'id-2', name: 'Account B', revenue: 750000 },
],
});
const fetchXml = `
`;
const result = await mockGenerator.context.webAPI.retrieveMultipleRecords(
'account',
'?fetchXml=' + encodeURIComponent(fetchXml)
);
expect(result.entities.length).toBe(2);
expect(result.entities[0].name).toBe('Account A');
});
it('Should update and delete records', async () => {
mockGenerator.metadata.initItems({
'@odata.context': '#accounts',
value: [{ accountid: 'test-id', name: 'Original Name' }],
});
// Update
await mockGenerator.context.webAPI.updateRecord('account', 'test-id', { name: 'Updated Name' });
const updated = mockGenerator.metadata.GetRow('account', 'test-id');
expect(updated.row.name).toEqual('Updated Name');
// Delete
const deleted = await mockGenerator.context.webAPI.deleteRecord('account', 'test-id');
expect(deleted.entityType).toEqual('account');
});
});
```
--------------------------------
### Import Mock Generator and Property Mocks
Source: https://github.com/shko-online/componentframework-mock/blob/main/README.md
Imports the necessary mock generator and property mock classes from the ComponentFramework Mock library.
```typescript
import { ComponentFrameworkMockGenerator, LookupPropertyMock } from '@shko.online/componentframework-mock';
```
--------------------------------
### Test Standard PCF Controls with ComponentFrameworkMockGenerator
Source: https://context7.com/shko-online/componentframework-mock/llms.txt
Tests standard DOM-based PCF controls using ComponentFrameworkMockGenerator. Initializes the mock environment, sets property values, simulates user interactions, and verifies output changes. Requires the control class, property mocks, and a DOM container.
```typescript
import { ComponentFrameworkMockGenerator, LookupPropertyMock } from '@shko.online/componentframework-mock';
import { OwnerLookup } from './OwnerLookup';
import { IInputs, IOutputs } from './OwnerLookup/generated/ManifestTypes';
describe('OwnerLookup', () => {
let mockGenerator: ComponentFrameworkMockGenerator;
beforeEach(() => {
const container = document.createElement('div');
mockGenerator = new ComponentFrameworkMockGenerator(
OwnerLookup,
{
value: LookupPropertyMock,
},
container,
);
// Set initial values using _SetCanvasItems
mockGenerator.context._SetCanvasItems({
value: {
entityType: 'team',
id: 'guid1',
name: 'Shko Online',
},
});
// Configure user settings
mockGenerator.context.userSettings.userId = 'MyUserId';
mockGenerator.context.userSettings.userName = 'Betim Beja';
document.body.appendChild(container);
});
it('Should render lookup value', () => {
mockGenerator.ExecuteInit();
mockGenerator.ExecuteUpdateView();
expect(mockGenerator.container).toMatchSnapshot();
});
it('Should detect output changes', () => {
mockGenerator.ExecuteInit();
mockGenerator.ExecuteUpdateView();
// Simulate user interaction
const button = mockGenerator.container.getElementsByTagName('button')[0];
button.click();
// Verify updatedProperties contains changed fields
expect(mockGenerator.context.updatedProperties).toStrictEqual(['value', 'parameters']);
expect(mockGenerator.onOutputChanged.called).toBeTruthy();
});
});
```
--------------------------------
### Mock PCF Formatting API for Locale-Aware Formatting
Source: https://context7.com/shko-online/componentframework-mock/llms.txt
Provides a mock implementation of the PCF Formatting API, enabling locale-aware formatting of various data types including currencies, numbers, and dates. This mock is essential for testing components that rely on the PCF's built-in formatting capabilities without needing a live environment.
```typescript
import { FormattingMock } from '@shko.online/componentframework-mock';
describe('FormattingMock', () => {
let formatting: FormattingMock;
beforeEach(() => {
formatting = new FormattingMock();
});
it('Should format currency values', () => {
expect(formatting.formatCurrency(100500, 2, '$')).toEqual('$100,500.00');
expect(formatting.formatCurrency(100600, 2, '€')).toEqual('€100,600.00');
expect(formatting.formatCurrency(100100)).toEqual('100,100');
});
it('Should format decimal values', () => {
expect(formatting.formatDecimal(10098, 2)).toEqual('10,098.00');
expect(formatting.formatDecimal(1234.5678, 3)).toEqual('1,234.568');
});
it('Should format integers', () => {
expect(formatting.formatInteger(1000000)).toEqual('1,000,000');
});
});
```
--------------------------------
### Set Canvas Item State
Source: https://github.com/shko-online/componentframework-mock/blob/main/README.md
Initializes or binds the state of the in-memory database for the mock component using the _SetCanvasItems method.
```typescript
mockGenerator.context._SetCanvasItems({
value: {
entityType: 'team',
id: 'guid1',
name: 'Shko Online',
},
});
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.