close
The Wayback Machine - https://web.archive.org/web/20200915041934/https://github.com/atata-framework/atata/issues/339
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to use FindBy with data from external resource (JSON, Resources.resx, etc.) #339

Open
alex-gagnon-firebrand opened this issue Jan 16, 2020 · 5 comments
Labels

Comments

@alex-gagnon-firebrand
Copy link

@alex-gagnon-firebrand alex-gagnon-firebrand commented Jan 16, 2020

Hello,

I am testing an application where I would ideally like to contain all my Id's, CSS selectors, etc. and then load them into the page objects FindBy. The reason for this being that I run these tests across multiple builds and databases that may have minor discrepancies in say, an Id field, but in the end is the same application.

current example:

// DB-1 id="id_in_div_3"
// DB-2 id="id_in_div_4"
[FindById("id_in_div_3")]
public Button<_> MyButton { get; private set; }

desired example:

[FindById(SomeIdNameFromFileOrResource)]
public Button<_> MyButton { get; private set; }

I may be trying to go about this the wrong way, but is this possible?

@alex-gagnon-firebrand alex-gagnon-firebrand changed the title Find page objects with data file containing Id, CSS Selectors, etc. Is it possible to use FindBy with data from external resource (JSON, Resources.resx, etc.) Jan 16, 2020
@YevgeniyShunevych
Copy link
Member

@YevgeniyShunevych YevgeniyShunevych commented Jan 17, 2020

Hey,

With Atata you can do it this way:

// [SomeOtherCommonAttributes...]
public Button<_> MyButton =>
        Controls.Resolve<Button<_>>(nameof(MyButton), () => new[] { new FindByIdAttribute(Resources.SomeIdNameFromFileOrResource) });
@YevgeniyShunevych
Copy link
Member

@YevgeniyShunevych YevgeniyShunevych commented Jan 17, 2020

There is also an "exotic" way of marking page object properties with attributes depending on the environment, using preprocessor directives.

#if ENV1
        [FindById("id-for-env-1")]
#elif ENV2
        [FindById("id-for-env-2")]
#else
        [FindById("id-regular")]
#endif
        public Button<_> MyButton { get; private set; }

This approach can also be used, but when there is not a lot of such different locator places, as it can become a mess.

@alex-gagnon-firebrand
Copy link
Author

@alex-gagnon-firebrand alex-gagnon-firebrand commented Jan 17, 2020

Awesome, I'll give this a try!

I have another issue that I thought I resolved, but ended up finding another issue along with it. I have a Custom Select that finds the select's preceding sibling (which should be input) and sets the value there rather than the select field.
Initial code to set the value to input in

<div>
<input id="the-value-is-set-on-me" />
<select id="i-get-clicked-and-become-hidden"></select>
</div>

namespace My.WebPages
{
    /// <summary>
    /// Find by the <select> element and update the sibling <input>.
    /// </summary>
    /// <typeparam name="TOwner"></typeparam>
    [FindSettings(Visibility = Visibility.Any)]
    public class CustomSelect<TOwner> : Select<TOwner>
        where TOwner : PageObject<TOwner>
    {
        [FindFirst(OuterXPath = "preceding-sibling::", Visibility = Visibility.Any)]  // Issue is here I believe.
        [TraceLog]
        [PressTab]
        [WaitForOverlay]
        private TextInput<TOwner> AssociatedInput { get; set; }

        protected override void SetValue(string value)
        {
            Click().Wait(10);  // Click on <select> element.
            AssociatedInput.Set(value);
        }
    }
}

Current issue is that there are some locations that are similar to the above, but have additional siblings

<div>
<span>I'm an evil span preventing you from setting the input</span>
<input id="the-value-is-set-on-me" />
<select id="i-get-clicked-and-become-hidden"></select>
</div>

I did try FindLast - but this didn't work for me. I tried FindByXPath - still no luck. I tried a few other's and haven't quite figured out what i am missing. Perhaps this issue is not even what I suspect it is (that it the value is trying to be set to the element.

Error
ElementNotInteractable

@YevgeniyShunevych
Copy link
Member

@YevgeniyShunevych YevgeniyShunevych commented Jan 20, 2020

If you get ElementNotInteractable exception then that input might not be actually visible at that point, or visible but overlapped by another element. Ensure that it gets visible. Hard to say the reason 100%. Maybe you need to click that overlapping span. You need to investigate the changes of HTML during the clicks on that drop-down. Also detect (check logs) at what step an error is thrown, when you click the select or when try to set the value to input.

@alex-gagnon-firebrand
Copy link
Author

@alex-gagnon-firebrand alex-gagnon-firebrand commented Jan 22, 2020

I can confirm that the element is visible. In my custom select I added

AssociatedInput.Should.BeVisible();
AssociatedInput.Attributes.Id.Should.Equal("the-span-id") // fails
AssociatedInput.Attributes.Id.Should.Equal("the-value-is-set-on-me") // passes

I notice that when the site is launched via the web driver, that I cannot manually set the input field. I can type, but when I press tab or enter, it just reverts to the original value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.