Get help with testing, discuss unit testing strategies etc.


Post by KaguChan »

Hi forum,

on our page we have different views using a "card" layout, meaning that already rendered views are not shown when not needed, thus, navigating hiding the old view and showing the new view (rendering or bringing to front).
With this we can navigate through the site without loosing data in a form for exampe (when looking things up for instance).

Right now we try to test a form (reset password), requirering the username.
items: [
    {
      name: 'username',
      fieldLabel: 'Nutzername',
    },
    {
      name: 'token',
      fieldLabel: 'Token',
      bind: {
        hidden: '{!waitingForToken}',
        disabled: '{!waitingForToken}',
      },
    },
  ],
  
This view is always rendered after our login form (since you need the login form to open this view).
items: [
    {
      name: 'username',
      fieldLabel: 'Nutzername',
    },
    {
      inputType: 'password',
      name: 'password',
      fieldLabel: 'Passwort',
    },
  ],
Thus, a component query for "[name=username]" will always find two elements.
    {
      waitForCQVisible: 'userReset [text=Absenden]',
    },
    (next) => {
      const { mainView } = Ext.getApplication();
      [submit] = spec.cq('userReset [text=Absenden]');
      [userName] = spec.cq('userReset [name=username]');
      [token] = spec.cq('userReset [name=token]');
      [view] = spec.cq('userReset');

      form = view.getForm();
      viewModel = mainView.getViewModel();
      controller = mainView.getController();

      hooks.spy(form, 'isValid');
      hooks.spy(view, 'setLoading');

      Log.trace([], userName);
      next();
    },
    {
      diag: 'Check prerequisites',
    },
    (next) => {
      spec.ok(submit.disabled, 'Submit should be disabled at start');
      spec.notOk(token.isVisible(), 'Token should invisible at start');

      next();
    },
    {
      type: 'loremipsum[ENTER]',
      // target: 'userReset [name=username]',
      target: userName,
    },
In the last step in our test here, siesta does nothing.
Using "target: '[name=username]'" yields more then one components, so this wont work as well.
Using "target: 'userReset [name=username]'" as we did it above doesn't work too
Waited too long for: element "userReset [name=username]" to appear
Failed assertion `waitForElementVisible` 
Condition was not fullfilled during 10000ms
Action `"type : `loremipsum[ENTER]`"` failed to complete within 15000ms
The step in `t.chain()` call did not complete within required timeframe, chain can not proceed
The element is already there - via the "Log.trace" we can see it in the console.
In our login test this approach works well:
    (next) => {
      spec.ok(loginButton.disabled, 'login button is disabled at start');

      next();
    },
    { click: '[name=username]' },
    { type: '[ENTER]' },
    (next) => {
      spec.ok(form.isValid.called, 'form is validated');
      spec.notOk(view.setLoading.called, 'login process canceled');

      next();
    },
What are we doing wrong?

Regards
Kai

Post by mats »

You need to specify your action targets with enough specificity so that Siesta can pick the right one. It will not automatically pick the right target if you have multiple matches. One trick you can use is to add the 'visible' Component Query pseudo:
 Ext.ComponentQuery.query('form[title=Profile] field:visible');
https://docs.sencha.com/extjs/6.7.0/classic/Ext.ComponentQuery.html

Post by KaguChan »

Using the query "userReset [name=username]" already resolves only one object. As said, the test code with Log.trace logs exactly the needed object to the console.

Post by mats »

Ah now I see the mistake. By default, a target string is a CSS query. for CQ use leading >>:
      target: '>>userReset [name=username]',

Post by KaguChan »

Thank you, that fixed it

Post Reply