Skip to content

Commit

Permalink
Merge pull request apex-enterprise-patterns#6 from OrtooApps/feature/…
Browse files Browse the repository at this point in the history
…updates-after-qassign-implementations

Feature/updates after qassign implementations
  • Loading branch information
rob-baillie-ortoo authored Jan 12, 2022
2 parents 1286e62 + f129751 commit 32dff13
Show file tree
Hide file tree
Showing 29 changed files with 680 additions and 157 deletions.
9 changes: 7 additions & 2 deletions TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ Licenses that are needed with the source code and binary:
* Amoss - https://github.com/bobalicious/amoss/blob/main/LICENSE
* SObject Fabricator - https://github.com/bobalicious/SObjectFabricator/blob/master/LICENSE

* Docs at the top level about the ortoo Id

Remove need for data-name - reference the id info

Add library for getting LWC elements by their generated Ortoo Id
Add docs for the retrieval of elements

Look at the use of 'MockDatabase' in fflib
Look at:
SobjectUtils.getSobjectName
Expand All @@ -19,8 +26,6 @@ Look at:
* Try parent and datatable referencing a DML Service

* Standards
* data-name to identify elements in a test
* e.g. [data-name="cancel"]
* Labels should be:
* Imported into a static named _LABEL
* Referenced in an object named 'labels'.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ describe('c-confirmation-dialog', () => {
const expectedElement = element.shadowRoot.querySelector( 'c-modal div[slot="footer"]' );
expect( expectedElement ).not.toBe( null );

expect( expectedElement.querySelector( '[data-name="confirm"]' ).title ).not.toBe( null );
expect( expectedElement.querySelector( '[data-name="confirm"]' ).label ).not.toBe( null );
expect( expectedElement.querySelector( '[data-name="cancel"]' ).title ).not.toBe( null );
expect( expectedElement.querySelector( '[data-name="cancel"]' ).label ).not.toBe( null );
expect( expectedElement.querySelector( '[data-ortoo-elem-id="confirmation-confirm"]' ).title ).not.toBe( null );
expect( expectedElement.querySelector( '[data-ortoo-elem-id="confirmation-confirm"]' ).label ).not.toBe( null );
expect( expectedElement.querySelector( '[data-ortoo-elem-id="confirmation-cancel"]' ).title ).not.toBe( null );
expect( expectedElement.querySelector( '[data-ortoo-elem-id="confirmation-cancel"]' ).label ).not.toBe( null );
});

it('When set to visible, contains a div containing cancel and confirm buttons with the specified labels, directing them to the modal footer slot', () => {
Expand All @@ -64,10 +64,10 @@ describe('c-confirmation-dialog', () => {
const expectedElement = element.shadowRoot.querySelector( 'c-modal div[slot="footer"]' );
expect( expectedElement ).not.toBe( null );

expect( expectedElement.querySelector( '[data-name="confirm"]' ).title ).toBe( 'Confirm thing' );
expect( expectedElement.querySelector( '[data-name="confirm"]' ).label ).toBe( 'Confirm thing' );
expect( expectedElement.querySelector( '[data-name="cancel"]' ).title ).toBe( 'Cancel thing' );
expect( expectedElement.querySelector( '[data-name="cancel"]' ).label ).toBe( 'Cancel thing' );
expect( expectedElement.querySelector( '[data-ortoo-elem-id="confirmation-confirm"]' ).title ).toBe( 'Confirm thing' );
expect( expectedElement.querySelector( '[data-ortoo-elem-id="confirmation-confirm"]' ).label ).toBe( 'Confirm thing' );
expect( expectedElement.querySelector( '[data-ortoo-elem-id="confirmation-cancel"]' ).title ).toBe( 'Cancel thing' );
expect( expectedElement.querySelector( '[data-ortoo-elem-id="confirmation-cancel"]' ).label ).toBe( 'Cancel thing' );
});

it('When set to visible and passed a valid type, contains a div containing cancel and confirm buttons with the specified labels, directing them to the modal footer slot', () => {
Expand All @@ -81,8 +81,8 @@ describe('c-confirmation-dialog', () => {
const expectedElement = element.shadowRoot.querySelector( 'c-modal div[slot="footer"]' );
expect( expectedElement ).not.toBe( null );

expect( expectedElement.querySelector( '[data-name="confirm"]' ).label ).not.toBe( null );
expect( expectedElement.querySelector( '[data-name="cancel"]' ).label ).not.toBe( null );
expect( expectedElement.querySelector( '[data-ortoo-elem-id="confirmation-confirm"]' ).label ).not.toBe( null );
expect( expectedElement.querySelector( '[data-ortoo-elem-id="confirmation-cancel"]' ).label ).not.toBe( null );
});

it('When set to an invalid type, will throw an error', () => {
Expand Down Expand Up @@ -113,7 +113,7 @@ describe('c-confirmation-dialog', () => {
const cancelHandler = jest.fn();
element.addEventListener( 'cancel', cancelHandler ) ;

element.shadowRoot.querySelector( '[data-name="confirm"]' ).click();
element.shadowRoot.querySelector( '[data-ortoo-elem-id="confirmation-confirm"]' ).click();

expect( confirmHandler ).toHaveBeenCalled();
expect( confirmHandler.mock.calls[0][0].detail ).toBe( CONFIRM_MESSAGE );
Expand Down Expand Up @@ -142,7 +142,7 @@ describe('c-confirmation-dialog', () => {
const cancelHandler = jest.fn();
element.addEventListener( 'cancel', cancelHandler ) ;

element.shadowRoot.querySelector( '[data-name="cancel"]' ).click();
element.shadowRoot.querySelector( '[data-ortoo-elem-id="confirmation-cancel"]' ).click();

expect( cancelHandler ).toHaveBeenCalled();
expect( cancelHandler.mock.calls[0][0].detail ).toBe( CANCEL_MESSAGE );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<c-modal
visible={visible}
oncancel={handleCancel}
data-ortoo-elem-id={modalId}
>

<div slot="title">
Expand All @@ -13,24 +14,25 @@
</div>

<div slot="footer">
<lightning-button-group>
<lightning-button
variant="neutral"
name="cancel"
data-name="cancel"
label={cancelLabel}
title={cancelLabel}
onclick={handleCancel}
></lightning-button>
<lightning-button
variant="brand"
name="confirm"
data-name="confirm"
label={confirmLabel}
title={confirmLabel}
onclick={handleConfirm}
></lightning-button>
</lightning-button-group>

<lightning-button
data-ortoo-elem-id={cancelId}
class="slds-p-around_xxx-small"
variant="neutral"
label={cancelLabel}
title={cancelLabel}
onclick={handleCancel}
></lightning-button>

<lightning-button
data-ortoo-elem-id={confirmId}
class="slds-p-around_xxx-small"
variant="brand"
label={confirmLabel}
title={confirmLabel}
onclick={handleConfirm}
></lightning-button>

</div>
</c-modal>
</template>
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { LightningElement, api } from 'lwc';
import configureElementIdGenerator from 'c/elementIdGenerator';

import CONFIRM_LABEL from '@salesforce/label/c.ortoo_core_confirm';
import CANCEL_LABEL from '@salesforce/label/c.ortoo_core_cancel';
Expand Down Expand Up @@ -70,7 +71,16 @@ export default class ConfirmationDialog extends LightningElement {

@api visible;

@api ortooElemIdPrefix = 'confirmation';

ortooIdConfiguration = {
modalId: '',
cancelId: 'cancel',
confirmId: 'confirm',
}

connectedCallback() {
configureElementIdGenerator( this );
this.confirmLabel = this.confirmLabel ? this.confirmLabel : buttonLabels[ this.type ].confirm;
this.cancelLabel = this.cancelLabel ? this.cancelLabel : buttonLabels[ this.type ].cancel;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import configureFindElement from 'c/elementFinder';

describe( 'configureFindElement', () => {
it( 'will add a "findElement" function against the passed object', () => {

const objectToRunAgainst = {};

configureFindElement( objectToRunAgainst );

expect( objectToRunAgainst.findElement ).toBeDefined();
});
});

describe( 'findElement', () => {
it( 'will ask the bound object for the element with the specified data-ortoo-elem-id', () => {

const mockQuerySelector = jest.fn();

const objectToRunAgainst = {
template: {
querySelector: mockQuerySelector
}
};
mockQuerySelector.mockReturnValueOnce( 'the element' );

configureFindElement( objectToRunAgainst );

const response = objectToRunAgainst.findElement( 'test-element' );

expect( response ).toBe( 'the element' );
expect( mockQuerySelector ).toBeCalledWith( '[data-ortoo-elem-id="test-element"]' );
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Will bind a function that will allow the bound LWC to 'findElement' passing an Ortoo Element Id.
*
* Should be bound in the connectedCallback of the LWC. E.g.
*
* connectedCallback() {
* configureFindElement( this );
* }
*
* @param bindTo The LWC to bind this function to
*/
const configureFindElement = bindTo => {
bindTo.findElement = function( ortooElemId ) {
return this.template.querySelector( `[data-ortoo-elem-id="${ortooElemId}"]` );
}.bind( bindTo );
};

export default configureFindElement;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>52.0</apiVersion>
<isExposed>false</isExposed>
</LightningComponentBundle>
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import configureElementIdGenerator from 'c/elementIdGenerator';

describe('configureElementIdGenerator', () => {
afterEach(() => {
});

it( 'will add properties to the passed object based on the ortooIdConfiguration property names with values built from the combination of the ortooIdConfiguration property values and the ortooElemIdPrefix', () => {

const objectToRunAgainst = {
ortooElemIdPrefix: 'theprefix',
ortooIdConfiguration: {
field1: 'thefield1',
field2: 'thefield2'
}
};

configureElementIdGenerator( objectToRunAgainst );

expect( objectToRunAgainst.field1 ).toBe( 'theprefix-thefield1' );
expect( objectToRunAgainst.field2 ).toBe( 'theprefix-thefield2' );
});

it( 'will skip the value if it is not specified', () => {

const objectToRunAgainst = {
ortooElemIdPrefix: 'theprefix',
ortooIdConfiguration: {
field1: '',
field2: 'thefield2'
}
};

configureElementIdGenerator( objectToRunAgainst );

expect( objectToRunAgainst.field1 ).toBe( 'theprefix' );
expect( objectToRunAgainst.field2 ).toBe( 'theprefix-thefield2' );
});

it( 'will throw an error if given an object with no ortooElemIdPrefix property', () => {

const objectToRunAgainst = {
ortooIdConfiguration: {
field1: '',
field2: 'thefield2'
}
};

expect( () => configureElementIdGenerator( objectToRunAgainst ) ).toThrow();
});
it( 'will throw an error if given an object with an empty ortooElemIdPrefix property', () => {

const objectToRunAgainst = {
ortooElemIdPrefix: '',
ortooIdConfiguration: {
field1: '',
field2: 'thefield2'
}
};

expect( () => configureElementIdGenerator( objectToRunAgainst ) ).toThrow();
});
it( 'will throw an error if given an object with a null ortooElemIdPrefix property', () => {

const objectToRunAgainst = {
ortooElemIdPrefix: null,
ortooIdConfiguration: {
field1: '',
field2: 'thefield2'
}
};

expect( () => configureElementIdGenerator( objectToRunAgainst ) ).toThrow();
});

it( 'will throw an error if given an object with no ortooIdConfiguration property', () => {

const objectToRunAgainst = {
ortooElemIdPrefix: 'theprefix'
};

expect( () => configureElementIdGenerator( objectToRunAgainst ) ).toThrow();
});

it( 'will not throw an error if given an object with an empty object for the ortooIdConfiguration property', () => {

const objectToRunAgainst = {
ortooElemIdPrefix: 'theprefix',
ortooIdConfiguration: {}
};

expect( () => configureElementIdGenerator( objectToRunAgainst ) ).not.toThrow();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const generateId = function( suffix ) {
return suffix ? this.ortooElemIdPrefix + '-' + suffix : this.ortooElemIdPrefix;;
}

const configureElementIdGenerator = function( bindTo ) {

if ( ! bindTo.ortooIdConfiguration ) {
throw 'configureGenerator called against an object with no ortooIdConfiguration member variable - this should contain the mapping of properties to their suffixes: ' + bindTo;
}

if ( ! bindTo.ortooElemIdPrefix ) {
throw new 'configureGenerator called against an object with no ortooElemIdPrefix member variable - this should contain the Id prefix' + bindTo;
}

for ( const idName in bindTo.ortooIdConfiguration ) {

Object.defineProperty( bindTo, idName, {
get: function() {
return generateId.call( bindTo, bindTo.ortooIdConfiguration[ idName ] );
}
});
}
}

export default configureElementIdGenerator;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>52.0</apiVersion>
<isExposed>false</isExposed>
</LightningComponentBundle>
Loading

0 comments on commit 32dff13

Please sign in to comment.