github.com/rposudnevskiy/consul@v1.4.5/ui-v2/tests/steps.js (about)

     1  /* eslint no-console: "off" */
     2  import Inflector from 'ember-inflector';
     3  import yadda from './helpers/yadda';
     4  import { currentURL, click, triggerKeyEvent, fillIn, find } from '@ember/test-helpers';
     5  import getDictionary from '@hashicorp/ember-cli-api-double/dictionary';
     6  import pages from 'consul-ui/tests/pages';
     7  import api from 'consul-ui/tests/helpers/api';
     8  // const dont = `( don't| shouldn't| can't)?`;
     9  const pluralize = function(str) {
    10    return Inflector.inflector.pluralize(str);
    11  };
    12  const create = function(number, name, value) {
    13    // don't return a promise here as
    14    // I don't need it to wait
    15    api.server.createList(name, number, value);
    16  };
    17  const lastRequest = function(method) {
    18    return api.server.history
    19      .slice(0)
    20      .reverse()
    21      .find(function(item) {
    22        return item.method === method;
    23      });
    24  };
    25  const fillInElement = function(page, name, value) {
    26    const cm = document.querySelector(`textarea[name="${name}"] + .CodeMirror`);
    27    if (cm) {
    28      cm.CodeMirror.setValue(value);
    29      return page;
    30    } else {
    31      return page.fillIn(name, value);
    32    }
    33  };
    34  var currentPage;
    35  export default function(assert) {
    36    return (
    37      yadda.localisation.English.library(
    38        getDictionary(function(model, cb) {
    39          switch (model) {
    40            case 'datacenter':
    41            case 'datacenters':
    42            case 'dcs':
    43              model = 'dc';
    44              break;
    45            case 'services':
    46              model = 'service';
    47              break;
    48            case 'nodes':
    49              model = 'node';
    50              break;
    51            case 'kvs':
    52              model = 'kv';
    53              break;
    54            case 'acls':
    55              model = 'acl';
    56              break;
    57            case 'sessions':
    58              model = 'session';
    59              break;
    60            case 'intentions':
    61              model = 'intention';
    62              break;
    63          }
    64          cb(null, model);
    65        }, yadda)
    66      )
    67        // doubles
    68        .given(['$number $model model[s]?', '$number $model models'], function(number, model) {
    69          return create(number, model);
    70        })
    71        .given(['$number $model model[s]? with the value "$value"'], function(number, model, value) {
    72          return create(number, model, value);
    73        })
    74        .given(
    75          ['$number $model model[s]? from yaml\n$yaml', '$number $model model[s]? from json\n$json'],
    76          function(number, model, data) {
    77            return create(number, model, data);
    78          }
    79        )
    80        .given(["I'm using a legacy token"], function(number, model, data) {
    81          window.localStorage['consul:token'] = JSON.stringify({ AccessorID: null, SecretID: 'id' });
    82        })
    83        // TODO: Abstract this away from HTTP
    84        .given(['the url "$url" responds with a $status status'], function(url, status) {
    85          return api.server.respondWithStatus(url.split('?')[0], parseInt(status));
    86        })
    87        .given(['the url "$url" responds with from yaml\n$yaml'], function(url, data) {
    88          api.server.respondWith(url.split('?')[0], data);
    89        })
    90        // interactions
    91        .when('I visit the $name page', function(name) {
    92          currentPage = pages[name];
    93          return currentPage.visit();
    94        })
    95        .when('I visit the $name page for the "$id" $model', function(name, id, model) {
    96          currentPage = pages[name];
    97          return currentPage.visit({
    98            [model]: id,
    99          });
   100        })
   101        .when(
   102          ['I visit the $name page for yaml\n$yaml', 'I visit the $name page for json\n$json'],
   103          function(name, data) {
   104            currentPage = pages[name];
   105            // TODO: Consider putting an assertion here for testing the current url
   106            // do I absolutely definitely need that all the time?
   107            return pages[name].visit(data);
   108          }
   109        )
   110        .when('I click "$selector"', function(selector) {
   111          return click(selector);
   112        })
   113        // TODO: Probably nicer to think of better vocab than having the 'without " rule'
   114        .when('I click (?!")$property(?!")', function(property) {
   115          try {
   116            return currentPage[property]();
   117          } catch (e) {
   118            console.error(e);
   119            throw new Error(`The '${property}' property on the page object doesn't exist`);
   120          }
   121        })
   122        .when('I click $prop on the $component', function(prop, component) {
   123          // Collection
   124          var obj;
   125          if (typeof currentPage[component].objectAt === 'function') {
   126            obj = currentPage[component].objectAt(0);
   127          } else {
   128            obj = currentPage[component];
   129          }
   130          const func = obj[prop].bind(obj);
   131          try {
   132            return func();
   133          } catch (e) {
   134            throw new Error(
   135              `The '${prop}' property on the '${component}' page object doesn't exist.\n${e.message}`
   136            );
   137          }
   138        })
   139        .when('I submit', function(selector) {
   140          return currentPage.submit();
   141        })
   142        .then('I fill in "$name" with "$value"', function(name, value) {
   143          return currentPage.fillIn(name, value);
   144        })
   145        .then(['I fill in with yaml\n$yaml', 'I fill in with json\n$json'], function(data) {
   146          return Object.keys(data).reduce(function(prev, item, i, arr) {
   147            return fillInElement(prev, item, data[item]);
   148          }, currentPage);
   149        })
   150        .then(
   151          ['I fill in the $form form with yaml\n$yaml', 'I fill in the $form with json\n$json'],
   152          function(form, data) {
   153            return Object.keys(data).reduce(function(prev, item, i, arr) {
   154              const name = `${form}[${item}]`;
   155              return fillInElement(prev, name, data[item]);
   156            }, currentPage);
   157          }
   158        )
   159        .then(['I type "$text" into "$selector"'], function(text, selector) {
   160          return fillIn(selector, text);
   161        })
   162        .then(['I type with yaml\n$yaml'], function(data) {
   163          const keys = Object.keys(data);
   164          return keys
   165            .reduce(function(prev, item, i, arr) {
   166              return prev.fillIn(item, data[item]);
   167            }, currentPage)
   168            .then(function() {
   169              return Promise.all(
   170                keys.map(function(item) {
   171                  return triggerKeyEvent(`[name="${item}"]`, 'keyup', 83); // TODO: This is 's', be more generic
   172                })
   173              );
   174            });
   175        })
   176        // debugging helpers
   177        .then('print the current url', function(url) {
   178          console.log(currentURL());
   179          return Promise.resolve();
   180        })
   181        .then('log the "$text"', function(text) {
   182          console.log(text);
   183          return Promise.resolve();
   184        })
   185        .then('pause for $milliseconds', function(milliseconds) {
   186          return new Promise(function(resolve) {
   187            setTimeout(resolve, milliseconds);
   188          });
   189        })
   190        // assertions
   191        .then('a $method request is made to "$url" with the body from yaml\n$yaml', function(
   192          method,
   193          url,
   194          data
   195        ) {
   196          const request = api.server.history[api.server.history.length - 2];
   197          assert.equal(
   198            request.method,
   199            method,
   200            `Expected the request method to be ${method}, was ${request.method}`
   201          );
   202          assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
   203          const body = JSON.parse(request.requestBody);
   204          Object.keys(data).forEach(function(key, i, arr) {
   205            assert.deepEqual(
   206              body[key],
   207              data[key],
   208              `Expected the payload to contain ${key} equaling ${data[key]}, ${key} was ${body[key]}`
   209            );
   210          });
   211        })
   212        // TODO: This one can replace the above one, it covers more use cases
   213        // also DRY it out a bit
   214        .then('a $method request is made to "$url" from yaml\n$yaml', function(method, url, yaml) {
   215          const request = api.server.history[api.server.history.length - 2];
   216          assert.equal(
   217            request.method,
   218            method,
   219            `Expected the request method to be ${method}, was ${request.method}`
   220          );
   221          assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
   222          let data = yaml.body || {};
   223          const body = JSON.parse(request.requestBody);
   224          Object.keys(data).forEach(function(key, i, arr) {
   225            assert.equal(
   226              body[key],
   227              data[key],
   228              `Expected the payload to contain ${key} to equal ${body[key]}, ${key} was ${data[key]}`
   229            );
   230          });
   231          data = yaml.headers || {};
   232          const headers = request.requestHeaders;
   233          Object.keys(data).forEach(function(key, i, arr) {
   234            assert.equal(
   235              headers[key],
   236              data[key],
   237              `Expected the payload to contain ${key} to equal ${headers[key]}, ${key} was ${
   238                data[key]
   239              }`
   240            );
   241          });
   242        })
   243        .then('a $method request is made to "$url" with the body "$body"', function(
   244          method,
   245          url,
   246          data
   247        ) {
   248          const request = api.server.history[api.server.history.length - 2];
   249          assert.equal(
   250            request.method,
   251            method,
   252            `Expected the request method to be ${method}, was ${request.method}`
   253          );
   254          assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
   255          const body = request.requestBody;
   256          assert.equal(body, data, `Expected the request body to be ${data}, was ${body}`);
   257        })
   258        .then('a $method request is made to "$url" with no body', function(method, url) {
   259          const request = api.server.history[api.server.history.length - 2];
   260          assert.equal(
   261            request.method,
   262            method,
   263            `Expected the request method to be ${method}, was ${request.method}`
   264          );
   265          assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
   266          const body = request.requestBody;
   267          assert.equal(body, null, `Expected the request body to be null, was ${body}`);
   268        })
   269  
   270        .then('a $method request is made to "$url"', function(method, url) {
   271          const request = api.server.history[api.server.history.length - 2];
   272          assert.equal(
   273            request.method,
   274            method,
   275            `Expected the request method to be ${method}, was ${request.method}`
   276          );
   277          assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
   278        })
   279        .then('the last $method request was made to "$url"', function(method, url) {
   280          const request = lastRequest(method);
   281          assert.equal(
   282            request.method,
   283            method,
   284            `Expected the request method to be ${method}, was ${request.method}`
   285          );
   286          assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
   287        })
   288        .then('the last $method request was made to "$url" with the body from yaml\n$yaml', function(
   289          method,
   290          url,
   291          data
   292        ) {
   293          const request = lastRequest(method);
   294          assert.ok(request, `Expected a ${method} request`);
   295          assert.equal(
   296            request.method,
   297            method,
   298            `Expected the request method to be ${method}, was ${request.method}`
   299          );
   300          assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
   301          const body = JSON.parse(request.requestBody);
   302          Object.keys(data).forEach(function(key, i, arr) {
   303            assert.deepEqual(
   304              body[key],
   305              data[key],
   306              `Expected the payload to contain ${key} equaling ${data[key]}, ${key} was ${body[key]}`
   307            );
   308          });
   309        })
   310        .then('the last $method requests were like yaml\n$yaml', function(method, data) {
   311          const requests = api.server.history.reverse().filter(function(item) {
   312            return item.method === method;
   313          });
   314          data.reverse().forEach(function(item, i, arr) {
   315            assert.equal(
   316              requests[i].url,
   317              item,
   318              `Expected the request url to be ${item}, was ${requests[i].url}`
   319            );
   320          });
   321        })
   322        .then('the url should be $url', function(url) {
   323          // TODO: nice! $url should be wrapped in ""
   324          if (url === "''") {
   325            url = '';
   326          }
   327          const current = currentURL() || '';
   328          assert.equal(current, url, `Expected the url to be ${url} was ${current}`);
   329        })
   330        .then(['I see $num $model', 'I see $num $model model', 'I see $num $model models'], function(
   331          num,
   332          model
   333        ) {
   334          const len = currentPage[pluralize(model)].filter(function(item) {
   335            return item.isVisible;
   336          }).length;
   337  
   338          assert.equal(len, num, `Expected ${num} ${pluralize(model)}, saw ${len}`);
   339        })
   340        // TODO: I${ dont } see
   341        .then([`I see $num $model model[s]? with the $property "$value"`], function(
   342          // negate,
   343          num,
   344          model,
   345          property,
   346          value
   347        ) {
   348          const len = currentPage[pluralize(model)].filter(function(item) {
   349            return item.isVisible && item[property] == value;
   350          }).length;
   351          assert.equal(
   352            len,
   353            num,
   354            `Expected ${num} ${pluralize(model)} with ${property} set to "${value}", saw ${len}`
   355          );
   356        })
   357        // TODO: Make this accept a 'contains' word so you can search for text containing also
   358        .then('I have settings like yaml\n$yaml', function(data) {
   359          // TODO: Inject this
   360          const settings = window.localStorage;
   361          Object.keys(data).forEach(function(prop) {
   362            const actual = settings.getItem(prop);
   363            const expected = data[prop];
   364            assert.strictEqual(actual, expected, `Expected settings to be ${expected} was ${actual}`);
   365          });
   366        })
   367        .then('I see $property on the $component like yaml\n$yaml', function(
   368          property,
   369          component,
   370          yaml
   371        ) {
   372          const _component = currentPage[component];
   373          const iterator = new Array(_component.length).fill(true);
   374          // this will catch if we get aren't managing to select a component
   375          assert.ok(iterator.length > 0);
   376          iterator.forEach(function(item, i, arr) {
   377            const actual =
   378              typeof _component.objectAt(i)[property] === 'undefined'
   379                ? null
   380                : _component.objectAt(i)[property];
   381  
   382            // anything coming from the DOM is going to be text/strings
   383            // if the yaml has numbers, cast them to strings
   384            // TODO: This would get problematic for deeper objects
   385            // will have to look to do this recursively
   386            const expected = typeof yaml[i] === 'number' ? yaml[i].toString() : yaml[i];
   387  
   388            assert.deepEqual(
   389              actual,
   390              expected,
   391              `Expected to see ${property} on ${component}[${i}] as ${JSON.stringify(
   392                expected
   393              )}, was ${JSON.stringify(actual)}`
   394            );
   395          });
   396        })
   397        .then(['I see $property on the $component'], function(property, component) {
   398          // TODO: Time to work on repetition
   399          // Collection
   400          var obj;
   401          if (typeof currentPage[component].objectAt === 'function') {
   402            obj = currentPage[component].objectAt(0);
   403          } else {
   404            obj = currentPage[component];
   405          }
   406          let _component;
   407          if (typeof obj === 'function') {
   408            const func = obj[property].bind(obj);
   409            try {
   410              _component = func();
   411            } catch (e) {
   412              console.error(e);
   413              throw new Error(
   414                `The '${property}' property on the '${component}' page object doesn't exist`
   415              );
   416            }
   417          } else {
   418            _component = obj;
   419          }
   420          assert.ok(_component[property], `Expected to see ${property} on ${component}`);
   421        })
   422        .then(["I don't see $property on the $component"], function(property, component) {
   423          // Collection
   424          var obj;
   425          if (typeof currentPage[component].objectAt === 'function') {
   426            obj = currentPage[component].objectAt(0);
   427          } else {
   428            obj = currentPage[component];
   429          }
   430          const func = obj[property].bind(obj);
   431          assert.throws(
   432            function() {
   433              func();
   434            },
   435            function(e) {
   436              return e.toString().indexOf('Element not found') !== -1;
   437            },
   438            `Expected to not see ${property} on ${component}`
   439          );
   440        })
   441        .then(["I don't see $property"], function(property) {
   442          assert.throws(
   443            function() {
   444              currentPage[property]();
   445            },
   446            function(e) {
   447              return e.toString().indexOf('Element not found') !== -1;
   448            },
   449            `Expected to not see ${property}`
   450          );
   451        })
   452        .then(['I see $property'], function(property) {
   453          assert.ok(currentPage[property], `Expected to see ${property}`);
   454        })
   455        .then(['I see $property like "$value"'], function(property, value) {
   456          assert.equal(
   457            currentPage[property],
   458            value,
   459            `Expected to see ${property}, was ${currentPage[property]}`
   460          );
   461        })
   462        .then(['I see the text "$text" in "$selector"'], function(text, selector) {
   463          assert.ok(
   464            find(selector).textContent.indexOf(text) !== -1,
   465            `Expected to see "${text}" in "${selector}"`
   466          );
   467        })
   468        // TODO: Think of better language
   469        // TODO: These should be mergeable
   470        .then(['"$selector" has the "$class" class'], function(selector, cls) {
   471          // because `find` doesn't work, guessing its sandboxed to ember's container
   472          assert.ok(
   473            document.querySelector(selector).classList.contains(cls),
   474            `Expected [class] to contain ${cls} on ${selector}`
   475          );
   476        })
   477        .then(['"$selector" doesn\'t have the "$class" class'], function(selector, cls) {
   478          assert.ok(
   479            !document.querySelector(selector).classList.contains(cls),
   480            `Expected [class] not to contain ${cls} on ${selector}`
   481          );
   482        })
   483        .then('ok', function() {
   484          assert.ok(true);
   485        })
   486    );
   487  }