In Serenity Cucumber, some methods do not scroll the element into the view port: for example, the getValue() method will just get that value and not scroll the browser so that the element is in view, which causes the report to just show a screen shot of the top of the page, but not the element that is being interacted with.
Example current method:
#Step("read first name")
public String readFirstName() {
return $(ContactPage.firstNameField).getValue();
}
Example of my attempt(s) to scroll the element into view, so it shows on the screenshot:
#Step("read first name")
public String readFirstName() {
new ScrollToBy(ContactPage.firstNameField).andAlignToTop();
return $(ContactPage.firstNameField).getValue();
}
You could use something like screenplay pattern questions/tasks for reading off-screen text.
#Subject("the displayed text")
public class TextValue implements Question<String> {
private Target target
#Override
public String answeredBy(Actor actor) {
return target.resolveFor(actor).getText();
}
private TextValue(Target target) {
this.target = target;
}
public static Question<String> of(Target target) { return new TextValue(target); }
}
Then in your steps...
theActorInTheSpotlight().wasAbleTo(Scroll.to(ContactPage.firstNameField));
theActorInTheSpotlight().should(eventually(
seeThat(the(TextValue.of(ContactPage.firstNameField)),
isEqualTo(expectedValue))
));
Related
I've been working in this project for abou a week and haven't find a solution to my problem.
For testing purposes I create a simple new DeclarativeComponent which is a panelGroupLayout that contains 2 OutputText. After that I deploy the jar file and add it to my other Fusion web application libraries.
I want to add this DeclarativeComponent in another UIComponent at runtime by pressing a button which contains the next code in the javabean:
`public void addComponent(ActionEvent actionEvent)
{
// Add event code here...
createOutputComponent();
}
private void createOutputComponent()
{
CuadroDeTextoComponent ui = new CuadroDeTextoComponent(); //This is my Declarative Component
UIComponent parentUIComponent = getPglComponente(); This is the panelGrouopLayout in which i want to add my declarativeComponent
addComponent(parentUIComponent, ui);
}
public void addComponent(UIComponent parentUIComponent, UIXDeclarativeComponent childUIComponent)
{
parentUIComponent.getChildren().add(childUIComponent);
AdfFacesContext.getCurrentInstance().addPartialTarget(parentUIComponent);
}`
I have tried draging the declarative component and it works, but when I do it dynamically the component doesn't display
For your component to display you may need to add a PPR refresh to it's parent element :
In your case :
public void addComponent(ActionEvent actionEvent)
{
// Add event code here...
createOutputComponent();
}
private void createOutputComponent()
{
CuadroDeTextoComponent ui = new CuadroDeTextoComponent(); //This is my Declarative Component
UIComponent parentUIComponent = getPglComponente(); This is the panelGrouopLayout in which i want to add my declarativeComponent
addComponent(parentUIComponent, ui);
addPPR(parentUIComponent); //Refresh the parent component
}
public void addComponent(UIComponent parentUIComponent, UIXDeclarativeComponent childUIComponent)
{
parentUIComponent.getChildren().add(childUIComponent);
AdfFacesContext.getCurrentInstance().addPartialTarget(parentUIComponent);
}
public static void addPPR(UIComponent component) {
if (component != null) {
AdfFacesContext.getCurrentInstance().addPartialTarget(component.getParent());
}
}
I'm creating intelliJ plugin and registering my action , inside my action i want to show an input dialog with multiple text boxes, how do I do that ?
I have an example of showing only one text box -
String txt= Messages.showInputDialog(project, "What is your name?",
"Input your name", Messages.getQuestionIcon());
I agree with #AKT with extending the DialogWrapper but suggest overriding doOKAction:
#Override
protected void doOKAction() {
if (getOKAction().isEnabled()) {
// custom logic
System.out.println("custom ok action logic");
close(OK_EXIT_CODE);
}
}
Or, if you just want your data out without the Action mess, add a custom method:
public class SearchDialog extends DialogWrapper {
...
public String getQuery() {
return "my custom query";
}
}
You can use it like:
SearchDialog dialog = new SearchDialog();
dialog.showAndGet(); // Maybe check if ok or cancel was pressed
String myQuery = dialog.getQuery();
System.out.println("my query: " + myQuery);
Create a new GUI Form (form + class). Class should extend DialogWrapper and override methods.
Inside createCenterPanel() return your root JPanel. You can set any default values, add event listeners to text box, etc., before returning JPanel.
Implement an Action interface where you want to get the value when OK button is clicked. Pass this action to your form class.
getOKAction() should return this action.
Following code is from a plugin i'm currently working on. Hopefully this will give you some idea but will have to adapt it to your need.
public class ReleaseNoteDialog extends DialogWrapper implements Action {
private JTextArea txtReleaseNote;
private JPanel panelWrapper;
.......
protected JComponent createCenterPanel() {
......
return panelWrapper;
}
......
#Override
protected Action getOKAction() {
return this;
}
.......
#Override
public void actionPerformed(ActionEvent e) {
// save value to project state
super.doOKAction();
}
I have a use case where a modal dialog has three set of Addresses of checkbox (Address A, Address B, Other Address) divided in separate divs for each address type for the user to select one address.
Each address type has their own set of TextFields for showing Name, House no, Street, City, Postal code and country.
So far so good. I was able to handle the selection of Address and pass the textfield values to the model. The model is getting reflected with the selected address.
On click of the "OK" button of Modal Window, (AjaxLink), there is a sub-panel (under another main panel, having all the address readonly textfields in it) which has to display the selected address type. But it isnt getting refresh. But the textfields model is having the updated values. (I have found this during debug)
Have tried everything on this site:
- using LoadableDetachableModel, setDefaultModel(), creating new instance of the Panel etc. but nothing is of use
i have also pasted the relevant code parts here. Request anyone who can guide me here as to what is going wrong and where I need to correct to get the sub-panel text fields refreshed on click of "OK' button of the modal.
thanks in advance
--ShipmentAddressSelectedPanel constructor Code
public ShipmentAddressSelectedPanel(String id, IModel<OrderDTO> orderDTOIModel) {
super(id, orderDTOIModel);
name = orderDTOIModel.getObject().getDeliveryAddress().getName();
streetAddress = subOrderDTOIModel.getObject().getDeliveryAddress().getStreet();
floor = orderDTOIModel.getObject().getDeliveryAddress().getFloor();
postalNumber = orderDTOIModel.getObject().getDeliveryAddress().getZipCode();
city = orderDTOIModel.getObject().getDeliveryAddress().getCity();
add(new TextField<>("name", new LoadableDetachableModel<String>() {
#Override
protected String load() {
return "" + name;
}
}));
add(new TextField<>("streetAddress", new LoadableDetachableModel<String>() {
#Override
protected String load() {
return "" + streetAddress;
}
}));
add(new TextField<>("floor", new LoadableDetachableModel<String>() {
#Override
protected String load() {
return "" + floor;
}
}));
//floor
add(new TextField<>("postalNumber", new LoadableDetachableModel<String>() {
#Override
protected String load() {
return "" + postalNumber;
}
}));
//postalNumber
add(new TextField<>("city", new LoadableDetachableModel<String>() {
#Override
protected String load() {
return "" + city;
}
}));
}
--code of onClick of AjaxLink ("Ok") button
add(new AjaxLink("saveAddress") {
#Override
public void onClick(final AjaxRequestTarget target) {
if (addressA.getValue().equals("true"))
{
onSaveAddress(target, getShipmentAddressModelFromDeliveryAddress(addressAModel.getObject()));
}
--Code of onSaveAddress where the logic refresh Panel is called from the main panel
#Override
public void onSaveAddress(AjaxRequestTarget target, ShipmentAddressModel shipmentAddressModel) {
ShipmentAddressSelectedPanel newShipmentAddressSelectedPanel = new ShipmentAddressSelectedPanel("showShipmentAddressSelected", orderDTOIModel);
newShipmentAddressSelectedPanel.setOutputMarkupId(true);
//newShipmentAddressSelectedPanel.setDefaultModelObject(orderDTOIModel);
target.add(newShipmentAddressSelectedPanel);
showAddressModal.close(target);
}
You're creating a new ShipmentAddressSelectedPanel, but it doesn't get added to the component tree.
Note that AjaxRequestTarget skips components, which are not inside the current page. You should have a log entry:
"Component .. with markupid: .. not rendered because it was already removed from page"
Note your usage of LDM is wrong, it should be:
//name = orderDTOIModel.getObject().getDeliveryAddress().getName();
add(new TextField<>("name", new LoadableDetachableModel<String>() {
#Override
protected String load() {
return orderDTOIModel.getObject().getDeliveryAddress().getName();
}
}));
Otherwise you'll pull out the name once only and never update when the model has changed.
If I have for example one master view on the left and one in the middle, each showing oder Java Beans/POJOs, can I use a shared detail view that somehow listens to the active beans of each view and then displays the currently selected one in more detail? A one to one relation is quite easy to manage by using your Context library.
#ViewDocking(areaId ="left", position=1, displayName="Profiles", menuEntry = #WindowMenuEntry(path = "", position=0), accelerator="Shortcut+1")
public class ProfileListView extends BorderPane implements LocalContextProvider {
private final SimpleContextContent content = new SimpleContextContent();
private final SimpleContext context = new SimpleContext(content);
#FXML
private ListView<Profile> listview;
public ProfileListView() {
load();
// add some profiles
listview.getItems().add(new Profile("Profile1"));
listview.getItems().add(new Profile("Profile2"));
listview.getItems().add(new Profile("Profile3"));
// setup selection listener
listview.getSelectionModel().selectedItemProperty().addListener((value, oldProfile, newProfile) -> {
// set active profile and remove old one
content.remove(oldProfile);
content.add(newProfile);
});
// setup double click listener
configureClickListener();
}
private Profile getSelectedProfile() {
return listview.getSelectionModel().getSelectedItem();
}
private void configureClickListener() {
listview.setOnMouseClicked(event -> {
// check if it was a double click
if(event.getClickCount() == 2) {
System.out.println(getSelectedProfile());
// inject into editor pane
// calls the procedure to create a tab in the center area...
}
});
}
private void load() {
FXMLLoaders.loadRoot(this);
}
#Override
public Context getLocalContext() {
return context;
}
}
This is one master view holding a list view of items.
The other one would be the same, docking to the right as another tab and holding POJOs of type 'Action'.
The detail view is here:
#ViewDocking(areaId = "right", displayName = "Properties", accelerator = "Shortcut+2", menuEntry = #WindowMenuEntry(path = "", position = 0), position = 1)
public class ProfilePropertiesView extends BorderPane implements LocalContextProvider, ActiveContextSensitive {
private Context activeContext;
private SimpleContextContent content = new SimpleContextContent();
private SimpleContext context = new SimpleContext(content);
private Profile profile;
private IWindowService service = new NullWindowService();
#FXML
private PropertySheet propertysheet;
public ProfilePropertiesView() {
load();
// retrieve framework service, TODO: use tracker
BundleContext ctx = FrameworkUtil.getBundle(getClass()).getBundleContext();
service = ctx.getService(ctx.getServiceReference(IWindowService.class));
// initialize callback
service.addCallback(title -> {
System.out.println("callback called " + title);
// update the property sheet ui by re-creating the items list
// updateUI();
// we can safely return null
return null;
});
// configure editor factory so the user is able to use a combobox
propertysheet.setPropertyEditorFactory(new CustomPropertyEditorFactory(service));
}
private void load() {
FXMLLoaders.loadRoot(this);
}
#Override
public Context getLocalContext() {
return context;
}
private void contextChanged() {
// find profile information
Profile found = activeContext.find(Profile.class);
// if the found profile is null, ignore it
if (found != null) {
// reset if profile is valid
if (profile != null) {
reset();
}
// create reference and register
profile = found;
register();
}
}
private void register() {
// retrieve observablelist of bean properties if some profile is selected
if(profile != null) {
ObservableList<Item> items = createDetailedList(profile);
propertysheet.getItems().setAll(items);
}
}
private void updateUI() {
// clear property elements and re-create them
reset();
// re-create items
ObservableList<Item> items = createDetailedList(profile);
propertysheet.getItems().addAll(items);
}
private ObservableList<Item> createDetailedList(Object bean) {
ObservableList<Item> list = FXCollections.observableArrayList();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass(), Object.class);
Arrays.stream(beanInfo.getPropertyDescriptors()).map(pd -> new DetailedBeanProperty(bean, pd)).forEach(list::add);
} catch (IntrospectionException e) {
e.printStackTrace();
}
return list;
}
private void reset() {
propertysheet.getItems().clear();
}
#Override
public void setActiveContext(Context activeContext) {
this.activeContext = activeContext;
this.activeContext.addContextListener(Profile.class, event -> contextChanged());
// trigger change
contextChanged();
}
}
The current ProfilePropertiesView is just configured to display the properties of the selected profile. I want it to be able to display the current information of the last selected POJO in the UI. That means that if the user selected a Profile from the ListView, that profile should be displayed in the properties view. If he selected an Action from the Table (which is displayed in the center), the properties of the Action should be displayed.
Do I just need to register a new ContextListener for the Action.class
POJO and then call a method to populate the PropertiesView? I was
unsure if this is the right solution...
Yes, just add another ContextListener to the activeContext for every POJO type you want to observe.
Also note that in the constructor of views it's better to use a ServiceTracker instead of looking for the service via BundleContext as the service might not be available yet, depending on the order the bundles are loaded.
You can find a sample which uses a ServiceTracker here: https://stackoverflow.com/a/35974498/506855
I have two view and their corresponding ViewModels and i want to send text from one view to another using MVVM Light as follows
in first viewmodel i am calling the following method
public void NavigatePage()
{
string temp = "temp value";
Messenger.Default.Send("temp");
Frame frame = Window.Current.Content as Frame;
if (frame != null) frame.Navigate(typeof(MyPage), temp);
}
while in page 2 view model i am having the following code
public MyViewModel()
{
Messenger.Default.Register<string>(this, MessageReceived);
}
private string test;
public string Test
{
get { return test; }
set { test = value; RaisePropertyChanged("Test");}
}
private void MessageReceived(string message)
{
Test = message;
}
when i debug my code the ctor of this viewmodel is getting called but the MessageReceived is not getting called hence property Test is never getting set, I am missing something, please help
Is the SecondViewModel actually created before you send the message? You can specify this in the ViewModelLocator class.
In the locator you have to register your viewmodel and CREATE it when the applications starts.
Like this:
SimpleIoc.Default.Register<SecondViewModel>(true);
With the true parameter the SecondViewModel will be created when the application is started! :)