Giter VIP home page Giter VIP logo

xrm-mock's Introduction

Build Status npm version Downloads Test Coverage

๐Ÿ“š xrm-mock

Join the chat at https://gitter.im/xrm-mock/Lobby

xrm-mock is a fake implementation of the Dynamics 365 Client API and Xrm object model. Written in TypeScript against @types/xrm definitions.

xrm-mock-generator is an opinionated toolset for building fake Xrm objects.

Installing

For the latest stable version

npm install xrm-mock -D

Usage

Import XrmMockGenerator in your unit test file

import { XrmMockGenerator } from "xrm-mock";

Initialise a global Xrm object

XrmMockGenerator.initialise();

Customise your form by adding attributes

XrmMockGenerator.Attribute.createBool("new_havingfun", true);

Invoke your code and make your assertions

Contact.onLoad();
expect(Xrm.Page.getAttribute("new_havingfun").getValue()).toBe(true);

Example

This example demonstrates a script with an onLoad event handler registered on a contact form. When invoked, it changes the firstname attribute's value to Bob. See the Wiki for a visual demo.

src/contact.ts

export default class Contact {
 public static onLoad() {
   Xrm.Page.getAttribute("firstname").setValue("Bob");
 }
}

test/contact.test.ts

import Contact from "../src/contact";
import { XrmMockGenerator } from "xrm-mock";

describe("Contact", () => {
  beforeEach(() => {
    XrmMockGenerator.initialise();
    XrmMockGenerator.Attribute.createString("firstname", "Joe");
  });

  it("should initially be called Joe", () => {
    let name = Xrm.Page.getAttribute("firstname").getValue();
    expect(name).toBe("Joe"); // Pass
  });

  it("should change name to Bob onLoad", () => {
    Contact.onLoad();
    let name = Xrm.Page.getAttribute("firstname").getValue();
    expect(name).toBe("Bob"); // Pass
  });
});

Contribute

  • Submit bugs
  • Implement a new function by inheriting @types/Xrm
    • Test your code using npm run test
    • Lint your code using npm run lint
    • Build your code using npm run build

Roadmap

  • Increased test coverage
  • Increased implementation against different versions of @types/Xrm (8.2 and 9)
  • Automatic generation of attributes from a given Dynamics organisation

xrm-mock's People

Contributors

ahmedelsawalhy avatar betimbeja avatar camelcasedave avatar daryllabar avatar dependabot[bot] avatar derekfinlinson avatar ecb-maintenance avatar iggsn avatar phuocle avatar roshangautam avatar scottdurow avatar vleong2332 avatar yagasoft avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xrm-mock's Issues

`XrmMockGenerator.Control.createBool()` funciton not exist

I have code in my function that I try test:

 Xrm.Page.getControl("zepcis_isbranch").setDisabled(true);

I init my XrmObjectModel :

  XrmMockGenerator.initialise();
           XrmMockGenerator.Attribute.createBool('zepcis_isbranch', true);

and when start testing then have exception:

FAILED TESTS:
  Company module
    Main form
      ร— test
        PhantomJS 2.1.1 (Windows 8 0.0.0)
      null is not an object (evaluating 'Xrm.Page.getControl('zepcis_isbranch').setDisabled')
      setAvailabilityLegalRelatedFields@tests/Entities/Company.spec.ts:9:615373
      OnLoad@tests/Entities/Company.spec.ts:9:608441
      tests/Entities/Company.spec.ts:9:231581

npm ERR! Test failed.  See above for more details.

but i haven't posibility create control with type bool. XrmMockGenerator.Control.createBool() function not exist.

Should Interfaces Be Prefixed with "I"

The Definitely Typed standard is to not preface interfaces with "I". Didn't know if we wanted to follow that standard, or continue to use the "I" prefix? I believe the reason they don't do it, is because pretty much everything could be an interface, so it get's a little verbose.

XrmMock.GridControlMock Does not implement setVisible()

The following code mocks a grid control:
XrmMockGenerator.initialise(); XrmMockGenerator.Control.createGrid("ContactGrid", true, "Contacts");
However if the function under test is purposed to hide/show that grid the test will fail with the following error:
"Method not implemented."

This appears to be due to src/xrm-mock/controls/gridcontrol/gridcontrol.mock.ts implementing a setVisible function that just throws the error. I suppose this is probably planned for a future release... but it could also be moved to the extended ControlMock class and implemented there.

can i test OnChange event?

as the title. i can mock field. but i cannot test the OnChange.

if yes, pls give me an example. thanks.

createSection Adds section to Tab twice

const tab = XrmMockGenerator.Tab.createTab("MyTab");
exepct(tab.sections.getLength()).toBe(0);
const section = XrmMockGenerator.Section.createSection("MySection", undefined, undefined, tab);
exepct(tab.sections.getLength()).toBe(1); // Fails.  Actual: 2

Add support for Control Notifications

Implement addNotification, clearNotification, and setNotification
Create applyNotification function to trigged the notification action
Create getNotifications to return the notifications for the mock standard control

Attribute fireOnChange

The fireOnChange mock is passing in the attribute to any event handlers when it should be passing in the execution context. That makes it difficult to test onChange methods since you need that execution context to get a form context.

Add empty lookup on form

Hi,

I am trying to add an empty lookup on form using:
XrmMockGenerator.Attribute.createLookup("parentaccountid", null);

then I try to find it on form using:

var formContext = XrmMockGenerator.getEventContext().getFormContext();
var lookupAttribute = formContext.getAttribute("parentaccountid");
var lookupAttributeValue = lookupAttribute.getValue();

I expect null ... but it returns an empty array
I checked behavior on real Dynamics form (tried both: v8.2 and v9.2) - lookup attribute is on the form but has no value - in both (v8.2 and v9.2) formContext.getAttribute().getValue() returns null as expected
What am I missing?
Thank you!

Here is the original code for .createLookup() call from xrm-mock package
01

02

3.0.0 didn't grab the latest code base

I'm getting an error in my project due to this line of code in autolookupcontrol.mock.js

var standardcontrol_mock_1 = require("./../standardcontrol/standardcontrol.mock");

Apparently my module loader doesn't like the "./.." syntax... But the actual code base had/has this syntax:

var standardcontrol_mock_1 = require("../standardcontrol/standardcontrol.mock");

So apparently, the methodology for building the npm package didn't generate the latest source...

Class 'LookupAttributeMock' incorrectly implements interface 'LookupAttribute'.

Hello,

When compiling the ts files I am getting the following errors:

node_modules/xrm-mock/dist/xrm-mock/attributes/lookupattribute/lookupattribute.mock.d.ts:4:22 - error TS2420: Class 'LookupAttributeMock' incorrectly implements interface 'LookupAttribute'.
Types of property 'controls' are incompatible.
Type 'ItemCollectionMock' is not assignable to type 'ItemCollection'.
Types of property 'forEach' are incompatible.
Type '{ (delegate: () => void): void; (delegate: IterativeDelegate): void; }' is not assignable to type '(delegate: IterativeDelegate) => void'.
Types of parameters 'delegate' and 'delegate' are incompatible.

4 export declare class LookupAttributeMock extends AttributeMock<LookupControlMock, Xrm.LookupValue[]> implements Xrm.Attributes.LookupAttribute {
~~~~~~~~~~~~~~~~~~~

node_modules/xrm-mock/dist/xrm-mock/controls/lookupcontrol/lookupcontrol.mock.d.ts:16:5 - error TS2416: Property 'removePreSearch' in type 'LookupControlMock'
is not assignable to the same property in base type 'LookupControl'.
Type '(handler: () => void) => void' is not assignable to type '(handler: ContextSensitiveHandler) => void'.
Types of parameters 'handler' and 'handler' are incompatible.

16 removePreSearch(handler: () => void): void;
~~~~~~~~~~~~~~~

node_modules/xrm-mock/dist/xrm-mock/controls/tab/tab.mock.d.ts:2:22 - error TS2420: Class 'TabMock' incorrectly implements interface 'Tab'.
Type 'TabMock' is missing the following properties from type 'Tab': addTabStateChange, removeTabStateChange

2 export declare class TabMock implements Xrm.Controls.Tab {
~~~~~~~

node_modules/xrm-mock/dist/xrm-mock/webapi/webapi.mock.d.ts:8:5 - error TS2416: Property 'createRecord' in type 'WebApiMock' is not assignable to the same property in base type 'WebApi'.
Type '(entityLogicalName: string, record: any) => PromiseLike' is not assignable to type '(entityLogicalName: string, record: any) => PromiseLike'.
Type 'PromiseLike' is not assignable to type 'PromiseLike'.
Type 'string' is not assignable to type 'CreateResponse'.

8 createRecord(entityLogicalName: string, record: any): Xrm.Async.PromiseLike;
~~~~~~~~~~~~

node_modules/xrm-mock/dist/xrm-mock/webapioffline/webapioffline.mock.d.ts:4:5 - error TS2416: Property 'createRecord' in type 'WebApiOfflineMock' is not assignable to the same property in base type 'WebApiOffline'.
Type '(entityLogicalName: string, record: any) => PromiseLike' is not assignable to type '(entityLogicalName: string, record: any) => PromiseLike'.
Type 'PromiseLike' is not assignable to type 'PromiseLike'.

4 createRecord(entityLogicalName: string, record: any): Xrm.Async.PromiseLike;
~~~~~~~~~~~~

node_modules/xrm-mock/dist/xrm-mock/webapionline/webapionline.mock.d.ts:8:5 - error TS2416: Property 'createRecord' in type 'WebApiOnlineMock' is not assignable to the same property in base type 'WebApiOnline'.
Type '(entityLogicalName: string, record: any) => PromiseLike' is not assignable to type '(entityLogicalName: string, record: any) => PromiseLike'.
Type 'PromiseLike' is not assignable to type 'PromiseLike'.

8 createRecord(entityLogicalName: string, record: any): Xrm.Async.PromiseLike;

Not sure if I am doing something incorrectly. Any help please?

Regards,
Jorge.

ItemCollection.forEach modifies collection

ForEach shouldn't modify the collection, just call the delegate for each item in the collection. Currently it is mapping the delegate, and updating the collection to the results of the map.

Error: removeOption function

Hi.

In the code below, I am trying to remove an option from an option set field but when I call getOptions() the option still there.

Code

import { } from "mocha";
import { expect } from "chai";
import { XrmMockGenerator } from "xrm-mock";

describe("On Load Form", () => {
    beforeEach(() => {
        XrmMockGenerator.initialise();
        XrmMockGenerator.Attribute.createOptionSet("countries", 0, [
            { text: "Austria", value: 0 },
            { text: "France", value: 1 },
            { text: "Spain", value: 2 }
        ]);
    });

    it("Filter optionset", () => {
        let formContext = XrmMockGenerator.eventContext.getFormContext();
        let control = formContext.getControl<Xrm.Controls.OptionSetControl>("countries");

        control.removeOption(2);

        let length = formContext.getAttribute<Xrm.Attributes.OptionSetAttribute>("countries").getOptions().length;

        expect(length).to.equal(2);
    });
});

Result
image

Xrm.ProcessFlow.ProcessManager Not Implemented Error

The business process flow tests that I am writing need the "moveNext" function but it throws a not implemented error, I can see that not all functions are implemented

How might I go about stubbing things like this, and are there plans to include in a future release?

Testing onChange event with async code

Hello,

I'm starting to use this for unit testing my front end code, so I need some help moving forward.

I have a Date attribute that will make an Xrm.WebApi.retrieveMultipleRecords call on the onChange handler. I saw the code sample on how to use sinon to mock the call, but it is sill async and I can't await it since fireOnChange is not "awaitable" (AFAIK).

Please point me in the right direction if there's any techniques or design patterns I'm missing.
Thanks in advace

use xrm-mock for Xrm v8 and v9 in one project

Hi,

Our app targets Dynamics v8, so we have bunch of tests for v8
At the same time we plan to migrate to v9, so in parallel we update the code and write tests against v9

We use aliases to add both xrm types (v8 and v9)

"@types/xrm8": "npm:@types/xrm@^8.2.8",
"@types/xrm9": "npm:@types/xrm@^9.0.70"

When initializing fake Xrm using XrmMockGenerator.initialize() clientContext in ContextMock can't be created via ClientContextMock because this mock object does not implement "isNetworkAvailable" property
Targeting just "@types/xrm8": "npm:@types/xrm@^8.2.8" because Xrm.Static does not have this "isNetworkAvailable" property in earlier version

image

image

Thank you!

getVisbile, setVisible on formselector is not implemented. headersection, footersection on Ui obeject are also not available.

getVisbile, setVisible on formselector is not implemented. headersection, footersection on Ui obeject are also available.

How do I write unit testing for the following implementations.

To hide the form selector:

formContext.ui.formSelector.items.forEach((f)=>{
function(f){
f.setVisible(false);
}
}

To deal with footer and header sections.

formContext.ui.headerSection.setBodyVisible(false);
formContext.ui.headersection.setCommandbarVisible(false);
formContext.ui.footerSection.setVisble(false);

'addOnLoad' in type 'GridControlMock' is not assignable to the same property in base type 'GridControl'

I am using following target packages :
"@types/xrm": "9.0.7"
"xrm-mock": "3.4.12",

When compiling the ts files I am getting the following errors:

Error TS2416 (TS) Property 'addOnLoad' in type 'GridControlMock' is not assignable to the same property in base type 'GridControl'.
Type '(handler: () => void) => void' is not assignable to type '(handler: ContextSensitiveHandler) => void'.
Types of parameters 'handler' and 'handler' are incompatible.
node_modules\xrm-mock\dist\xrm-mock\controls\gridcontrol\gridcontrol.mock.d.ts

Error TS2416 (TS) Property 'body' in type 'ExecuteResponseMock' is not assignable to the same property in base type 'ExecuteResponse'.
Type 'string' is not assignable to type 'ReadableStream'.
node_modules\xrm-mock\dist\xrm-mock\executeresponse\executeresponse.mock.d.ts

Error TS2416 (TS) Property 'type' in type 'ExecuteResponseMock' is not assignable to the same property in base type 'ExecuteResponse'.
Type 'string' is not assignable to type 'ResponseType'.
node_modules\xrm-mock\dist\xrm-mock\executeresponse\executeresponse.mock.d.ts

Creating control along with attribute

Hello @camelCaseDave ,

I saw that you started migration of xrm-mock-generator into this project so I'm gonna put this issue/question here. Are you going to implement creating control along with creating attribute , ie. via XrmMockGenerator.Attribute.createOptionSet method? Xrm.Page.getControl is not working (it returns Cannot read property 'getName' of undefined - in StandardControlMock.prototype.getName = function () { return this.control.getName(); };).

Have a nice day!

The getFormContext function is not implemented in onSave event

When an onSave event is fired, the "getFormContext" method is not implemented in the returned event.

The code below throws an Error with the message "getFormContext not implemented.".

let formContext: Xrm.FormContext;
entity.addOnSave((saveContext: Xrm.Events.SaveEventContext) => {
    formContext = saveContext.getFormContext();
});

entity.save();

`getAttribute('name').controls` should always contain controls that were added for the attribute

There is at least two ways to create controls in xrm-mock:

  • implicitly by just running Attribute.createLookup without passing controls parameter (default control is created);
  • by explicitly passing ControlComponent to Attribute.createLookup;
  • by running Control.createLookup.

But looks like neither of this functions fill getAttribute('name').controls array. This list is useful when we want to apply some validation to all controls of the attribute, for example.

Need Help : Trying to write unit test in Javascript

Hi,
The library looks very promising for mocking Xrm .
I am trying to write unit test using jest but "XrmMockGenerator.initialise()" is giving undefined.

Sample code.
var XrmMockGenerator = require('xrm-mock');

test('trying xrm-mock', () => {
var Xrm = XrmMockGenerator.initialise();

});

How to stub Xrm.Navigation.navigateTo() function?

I see in /src/xrm-mock/navigation/navigation.mock.ts that not all Xrm.Navigation functions are mocked. There's an error message suggesting to use Sinon.JS to stub certain functions, which I am attempting by attempting a very simple test:

it("should stub Xrm.Navigation.navigateTo", function() {
        const navigateToStub = sinon.stub(Xrm.Navigation, "navigateTo");
    });

This results in the following error:

TypeError: Cannot stub non-existent property navigateTo

It's not a deal-breaker even though the method under test navigates to a different entity after a specific function succeeds. It's just out of curiosity that I am trying to figure out how one might stub a function that is not implemented by xrm-mock just yet.

setVisible() do nothing

Hi, I have something like this in my controller I would like to test:

formContext.getAttribute("fieldName").controls.forEach(control => control.setVisible(true));

In my test I am setting this field like this:
xrmMockGenerator.XrmMockGenerator.Attribute.createString({
name: "fieldName", // Applies to all attributes
value: false // Applies to all standard attributes, but type is attribute specific
},
[
{
visible: true
}, {
visible: false
}
]
);

function setVisible(true) do nothing. setDisabled(true) works just fine.

Please am I doing something wrong or?

Thank you

Question: FormContext and Statecode

What is the correct way to add a statecode attribute to the formContext? I have been creating string attributes as shown in the examples i.e.

const stringAttribute = XrmMockGenerator.Attribute.createString("firstname", "Joe");

Then adding them to the formContext like

context.data.attributes = new ItemCollectionMock([stringAttribute]);

If I try to create a statecode though as below

const statecode = XrmMockGenerator.Attribute.createOptionSet("statecode", 0, [
  { text: "Active", value: 0 },
  { text: "Inactive", value: 1 },
]);

I get an error about a circular reference.

Thanks, Alan

Open to contributions?

Hi Dave!

I've accidentally came across this repo after checking some of Jason Lattimer's one! :)

I'm running 2 open source projects for Unit testing Dynamics CRM. FakeXrmEasy and FakeXrmEasy.js. First one is pretty mature now and I'll be spending more time on the other one now for mocking web api calls.

Was going to start a new repo for mocking the Xrm Page cause the only one I found was from Patrick Verbateen in CodePlex but it looks abandoned .... until I came across yours!

I think with your xrm mock project, plus the 2 FakeXrmEasy ones, then we're covered in terms of unit testing pretty much any CRM extension :)

Use strict versioning for @types/xrm

Hi Dave!

Hope all is ok! :)

This is somehow related to #6 .

At the minute trying to build the project against latest version of @types/xrm (9.0.14) breaks the build. However, running against version 9.0.7 works fine.

I think we could use a strict versioning to be added to the dependencies of package.json (i.e. use exactly "9.0.7" instead of "^9.0.7") it would make it more obvious which version this project depends on. And so when we have a version of xrm-mock compatible with latest xrm/types we could upgrade the package accordingly and also any package depending on xrm-mock will use exactly the same.

Context Mocks

Any plans to add support for mocking GlobalContext , EventContext etc to be able to mock a form event with executionContext and mock currently logged in user? Any help would be highly appreciated :)

How to properly use Form Context?

We are using Event and Form Context in our forms, and when writing tests with xrm-mock, the changes that are done in the code are then not reflected in the test.

Here is the test result:
Expected: "Notes (2)" Received: "Notes"

This is how my test looks like:

import { XrmMockGenerator }  from "xrm-mock"
import account from "../account_main"
import * as sinon from "sinon"

describe("account", () => {
    beforeEach(() => {
      XrmMockGenerator.initialise();
    });
   
    it("count notes and update the label", () => {
      XrmMockGenerator.Tab.createTab("notes", "Notes", true);
      var context = XrmMockGenerator.getEventContext();
      
      const stub = sinon.stub(Xrm.WebApi, "retrieveMultipleRecords").resolves({
        entities: ["1", "2"],
        nextLink: null
      });

      account.showAttachmentCount(context);
    
      let tab = context.formContext.ui.tabs.get('notes');

      expect(tab.getLabel()).toBe("Notes (2)"); // Pass
    });
   
});

This is the function that is being tested:

static showAttachmentCount(context: Xrm.Events.EventContext) {
        const formContext = context.getFormContext();

        var filter = "?$select=subject&$filter=_objectid_value eq (" + formContext.data.entity.getId() + ")";

        Xrm.WebApi.retrieveMultipleRecords("annotation", filter).then(notes => {
            if (notes.entities.length > 0) {
                var tab = formContext.ui.tabs.get('notes');
                
                if (tab !== null) {
                    console.log(tab.getLabel());
                    tab.setLabel(tab.getLabel() + ' (' + notes.entities.length.toString() + ')');
                }
            }
        }).catch();
    }

What am I doing wrong here?
Do I need to apply the changes to the context somehow?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.