How to realize ajax .done in livewire - laravel-livewire

I want to refresh some html in other container, not where the button is.
In native ajax is like this
.done(function(result){
$('#result').html(result);
});
how it works in livewire alpinejs?

you have 2 option
use Livewire Life Cycle Javascript Hooks
you can see the livewire javascript hooks in this link
Lifecycle Hooks
document.addEventListener("DOMContentLoaded", () => {
Livewire.hook('message.processed', (message, component) => {})
});
Use Browser Events Dispatching
Dispatching Browser Events
you can dispatch a browser event when ever you want in you backend like this
$this->dispatchBrowserEvent('name-updated', ['newName' => $value]);
and for js side you can use this code:
window.addEventListener('name-updated', event => {
alert('Name updated to: ' + event.detail.newName);
})

Related

Enzyme / React Unit test

I have this React functional UI only component, which has two props passed in, the second being a function that is passed from its parent component. The onClick calls 'delegates' to a function in the parent container component, this parent method is then responsible for dispatching to a redux store.
import React, {Component} from 'react';
import PropTypes from 'prop-types';
const BotShowUI = ({ bot, onClick }) => {
return(
<div id={bot.id} onClick={onClick}>
{bot.id} : {bot.text}
</div>
)
}
BotShowUI.propTypes = {
bot: PropTypes.object.isRequired,
onClick: PropTypes.func.isRequired
};
export default BotShowUI;
My test spec is, which uses Jasmine
import React, {Component} from 'react';
import { mount } from 'enzyme';
import BotShowUI from '../botShowUI';
function onClickFunction(){};
describe('botShowUI', () => {
const bot = {id: 1, isDone: false, text: 'bot 123'};
const expectedDivText = '1 : bot 123';
const wrapper = mount(<BotShowUI bot={bot} onClick={onClickFunction} />);
it(' div has been rendered ', () => {
expect(wrapper.find('div').first()).not.toBe(null);
});
it(' div displays the correct bot text ', () => {
expect(wrapper.find('div').first().text()).toEqual(expectedDivText)
});
it(' div click event fired ', () => {
wrapper.simulate('click');
expect(wrapper.state('onClick')).toBe(true);
});
});
This last assertion fails with
Chrome 57.0.2987 (Windows 10 0.0.0) botShowUI div click event fired FAILED
TypeError: Cannot read property 'onClick' of null
at ReactWrapper.state (webpack:///~/enzyme/build/ReactWrapper.js:825:24 <- tests.webpack.js:26303:25)
at Object.<anonymous> (webpack:///app/react/components/bots/_tests/botShowUI.spec.js:25:23 <- tests.webpack.js:25415:25)
wrapper.simulate('click'); works, but the next line fails
What is the correct way to assert that the click was fired ?
Do I have to drop into wrapper's props/children instead of using state ?
I'm not trying to test the parent container in any way, the two are isolated.
This test is only concerned with this UI component.
First thing is that onClick isn't on state, but on props, so you will have to access it by doing wrapper.props('onClick').
Secondly, to test whether onClick has been handled or not is to use a spy, rather than an empty function. If you do not want to use spy, you can still do that, but not the way you have done. If you are interested, I can post some pseudo-code for that too. But coming back to using spies, you can use a spy as the onClick prop. Below is the code for that. I have hand-written it, so please check for any syntax error, but you should get the idea on what needs to be done.
it('should call the onClick handler on click', () => {
const onClickFunction = sinon.spy()
wrapper = mount(<BotShowUI bot={bot} onClick={onClickFunction} />)
wrapper.simulate('click');
expect(onClickFunction).toHaveBeenCalled();
})
Based on Abhishek's answer here's my solution for Jasmine
it(' div click event fired ', () => {
let onClickFunction_spy = jasmine.createSpy('onClickFunction');
const wrapper = mount(<BotShowUI bot={bot} onClick={onClickFunction_spy} />);
wrapper.simulate('click');
expect(onClickFunction_spy).toHaveBeenCalled();
});
Hope this helps anyone.

Test functions passed as props to modal in React Redux

I am looking for a way to test the functions passed as props to a React Bootstrap modal in React Redux, generated in a similar way to here: https://stackoverflow.com/a/35641680/4401847.
I need to test functions passed as props through mapDispatchToProps/mergeProps with Chai and Mocha. The way I'm trying to do so is by dispatching actions which make the modal pop up
This would be an example of a test case, at least its first lines:
it("should dispatch an action when clicking a button", function (done) {
store.dispatch({
type: "modal/show",
modalType: "POST",
modalProps: {
mode: "add",
title "Create new post"
}
});
const modal = mount(<Provider store={store}><PostModal/><Provider/>);
setTimeOut(function() {
//I don't know how to access the functions passed as props via dispatchToProps and mergeProps.
});
});
Thank you very much

How to transition to route in Ember from global context?

I am integrating a chrome extension with an ember app. I have some chrome extension code in my app.js file:
window.sendToExtension = (message, callback) => {
chrome.runtime.sendMessage(extensionId, message, (response) => {
console.log('got response from extension!!', response)
if (response.path) {
//Here I need to tell the ember app the transition to the given path
}
})
}
this refers to window so I can't just call this.transitionTo. How can I transition to the route name the extension has told me to?
I figured it out!! All I had to do was add a beforeModel hook to the application route that did window.applicationRouteInstance = this and then I can access this globally, such as in my extension messaging code, to do applicationRouteInstance.transitionTo(response.path)
Also there's the new App.visit api coming in 2.3

ember event trigger order is different in app and tests

I have written this simple demo component to demonstrate a problem. The component code is below
App.FocusOutComponent = Em.Component.extend({
attributeBindings: ['tabindex'],
tagName: 'focus-out',
setFocus: function() {
console.log('clicked focus-out container');
this.$().find('button').focus();
console.log('focus set to button');
}.on('click'),
focussedOut: function() {
console.log('focussedOut from outer container');
}.on('focusOut'),
});
{{#focus-out id="focus-container" tabindex="-1"}}
<button id="text-button">Test Button</button>
{{/focus-out}}
When I run this and click on the focus-out element, this is the order of the logs. Link to demo
clicked focus-out container
focussedOut from outer container
focus set to button
Now when I am trying to write acceptance tests for this with the following code.
test('test visit / and click button', function() {
expect(0);
visit('/').then(function() {
find('focus-out').click();
console.log('after click in test');
});
});
The order of the logs are different. Link to demo.
clicked focus-out container
focus set to button
after click in test
focussedOut from outer container
The focusOut log got printed at the very end instead before the after click log. I was expecting the same order for the logs with just an additional log(after click) in the end.
Im not sure if this is a bug or something wrong with my code.
I also noticed another problem while executing tests. If I have focus on the chrome dev-tools while the tests are running, the focusOut event will not trigger at all.
Some help with this is much appreciated.
the click event doesn't set focus (being a back door route). You'll need to manually set focus then click if you want the same results.
Ember's Click Helper (sends mousedown/mouseup, then click)
function click(app, selector, context) {
var $el = app.testHelpers.findWithAssert(selector, context);
run($el, 'mousedown');
if ($el.is(':input')) {
var type = $el.prop('type');
if (type !== 'checkbox' && type !== 'radio' && type !== 'hidden') {
run($el, function(){
// Firefox does not trigger the `focusin` event if the window
// does not have focus. If the document doesn't have focus just
// use trigger('focusin') instead.
if (!document.hasFocus || document.hasFocus()) {
this.focus();
} else {
this.trigger('focusin');
}
});
}
}
run($el, 'mouseup');
run($el, 'click');
return app.testHelpers.wait();
}
Modified Test
test('test visit / and click button', function() {
expect(0);
visit('/').then(function() {
var el = find('focus-out');
el.focus();
click(el);
console.log('after click in test');
});
});
http://emberjs.jsbin.com/lefazevozi/1/edit?js,console,output
It's also important to note, that tearing down will also call the focus out event. So the main reason you were seeing the focusout at all was because on teardown it was losing focus from the button child.
Maybe focus should be set before mousedown on the click helper in the ember test, though I'm not sure what else that might affect, or if people wouldn't generally be expecting that since jquery doesn't do that.

AngularJS: how to invoke event handlers and detect bindings in tests

I want to write unit and e2e tests for various custom angularjs directives that add javascript event bindings to the elements they are attached to.
In tests, it's easy enough to simulate click and dblclick events using jQuery methods.
element("#id").click();
However, I am also binding mouseover, mouseout and contextmenu events, and haven't found a way to invoke these in e2e tests. The code below shows the approach I am taking.
it('should show a context menu when the user right clicks on a grid row',
function () {
//not currently triggering the context menu
var outerRow = element(".ngRow", "outer row");
var row = element(".ngRow:first > div", "row");
angular.element(row).triggerHandler("contextmenu");
expect(outerRow.attr("class")).toContain("open");
});
How can I get the contextmenu event to fire in tests?
Similarly, in unit tests for the directives, I want to be able to detect if an event binding has been attached to an element.
How can I achieve this?
Got to the bottom of this eventually. To trigger the events on elements selected using jQuery, jQuery obviously needs to be loaded. The problem is that, as explained here, the Angular runner runs the tests in an IFrame which doesn't have jQuery loaded.
However, you can extend the angular scenario dsl to execute code in the context of your e2e test where jQuery is loaded. The function below enables you execute any javascript method, or to fire any event:
//this function extends the Angular Scenario DSL to enable JQuery functions in e2e tests
angular.scenario.dsl('jqFunction', function () {
return function (selector, functionName /*, args */) {
var args = Array.prototype.slice.call(arguments, 2);
return this.addFutureAction(functionName, function ($window, $document, done) {
var $ = $window.$; // jQuery inside the iframe
var elem = $(selector);
if (!elem.length) {
return done('Selector ' + selector + ' did not match any elements.');
}
done(null, elem[functionName].apply(elem, args));
});
};
});
The following code uses the above function to fire the contextmenu event in an e2e test:
it('should show a context menu when the user right clicks on a grid row', function () {
var outerRow = element(".ngRow:first", "outer row");
jqFunction(".ngRow:first > div", "contextmenu");
expect(outerRow.attr("class")).toContain("open");
});