theintern / intern-examples

A collection of examples for the Intern testing library
theintern.io
85 stars 83 forks source link

Bug in page object example and example doesn't match intern-tutorial #45

Open nick-brady opened 7 years ago

nick-brady commented 7 years ago

I saw a helpful page object example that was added in the docs here with issue #16 .

The current example of how the page object is out of date with the new JS syntax used in the latest version of the intern-tutorial page.

jason0x43 commented 7 years ago

Could you add links to the specific page object example of interest, and also to the intern-tutorial page you're looking at? (The intern-tutorial hasn't been updated in quite some time.)

nick-brady commented 7 years ago

Hi @jason0x43 , absolutely. Thanks for the reply. Here is the example I was looking at.

Its also worth mentioning I'm having a lot of trouble getting the example to work.. I thought It was me not applying it correctly, though now I'm not sure. I'll explain here, but I'm admittedly not and expert with the finer points of JS.

In this portion this portion:

// methods on the page object and then verify
// that the expected result is returned
return indexPage
    .login('test', 'test')  // login is on the prototype of indexPage, so this is fine
    .then(function (loggedIn)

I still need to use the get method on remote to get the host (I don't see where/how this is done in the example). When I do this:

// methods on the page object and then verify
// that the expected result is returned
return indexPage.remote  // need to access remote here
    .get('http://localhost:3000/#/login')
    .login('test', 'test')
    .then(function (loggedIn)

Then login won't exist. Whatever is used as the prototype for objects returned by the leadfoot object don't seem to have the indexPage prototype somewhere down its prototype chain. I don't see a reason why it should with the code shown, but I haven't been able to figure out how to have it resolve as shown in that final code block.

THIS works, but then I add the get to my page object. The get should also be added to the docs example in that case so it is known this is the intension.

Something like...

// index.js

// methods on the page object and then verify
// that the expected result is returned
return indexPage
    .login('test', 'test')  // login is on the prototype of indexPage, so this is fine
    .then(function (loggedIn)
// page object

function LoginPage(remote) {  // Create function constructor
    this.remote = remote;
  }
LoginPage.prototype = {
   constructor: LoginPage,
   login: function (username, password) {
     return (this.remote
              .get(‘http://localhost:3000/#/login')  // add get to docs here
              .setFindTimeout(5000)
 ...

Doing this though, I'm not sure how I could continue chaining on with other page objects after I used the login method for the same reasons above where I was struggling

Also, If you do update the example, following the newer syntax looked like this for me if it saves you any time

define(function (require) {
    var registerSuite = require('intern!object');
    var assert = require('intern/chai!assert');
    var IndexPage = require('../support/pages/IndexPage');

    var indexPage;
    registerSuite({
        name: 'index',

        setup: function () {
            indexPage = new IndexPage(this.remote);
          },

        'login to dashboard': function () {
            return indexPage
                .login('me@email.com', 'password')
        }
    });
});
nick-brady commented 7 years ago

Sorry, I misread your comment earlier. The example can't be linked in from the project. The file is created through out the tutorial process. The example in question starts on line 220 of the readme though in the intern example you linked.

jason0x43 commented 7 years ago

So, the example in the guide (at https://theintern.github.io/intern/#page-objects) uses an architecture that many have found a bit tricky to work with, but it is technically workable. I'm still not sure what other example you're looking at, though. The intern-tutorial (https://github.com/theintern/intern-tutorial) doesn't mention page objects so far as I'm aware.

A somewhat easier way to implement page objects (at least to me) is to use helper functions (https://stackoverflow.com/questions/42837483/intern-js-how-to-return-pageobject-of-the-page-from-the-function-which-opens-it/42838529#42838529).

nick-brady commented 7 years ago

Hi @jason0x43 , yep, you are correct (and thank you for being so helpful!). I've figured this out using the example from SO you linked above.. trying to match your dedication here though, so this is what my original issue was more so following :)

The intern-tutorial does not use page objects in its example as you mentioned. The issue I ran into (and this is nitpicky) was when I was trying to add a page object to the intern-tutorial using the example here "Then, the page object would be used in tests instead of the this.remote object:":

which has syntax like:

// in tests/functional/index.js
define([
  'intern!object',
  'intern/chai!assert',
  '../support/pages/IndexPage'
], function (registerSuite, assert, IndexPage) {
  registerSuite(function () {
    var indexPage;
    return {

and translating that to fit into the example on the intern-turtorial which looks like this:

define(function (require) {
    var registerSuite = require('intern!object');
    var assert = require('intern/chai!assert');

    registerSuite({
        name: 'index',

        'greeting form': function () {

which I think would end up looking like this:

define(function (require) {
    var registerSuite = require('intern!object');
    var assert = require('intern/chai!assert');
        var indexPage = require('../support/pages/IndexPage')
        var IndexPage;

    registerSuite({
        name: 'index',
                setup: function () {
                    indexPage = new IndexPage(this.remote);
                 },
        'greeting form': function () {
            return indexPage.remote
                .get(require.toUrl('index.html'))
                .setFindTimeout(5000)

basically, the example in the docs uses older syntax, and the intern-tutorial uses newer syntax, and mapping between them was confusing (at least for me at first.. had to brush off some JS dust that piled up). I ended up implementing page objects as linked by that SO link as well :), very helpful.

I personally understand this now (implementing page objects with the alternative) if that is enough for the issue to close. Thanks again!