mdasberg / ng-apimock

Node plugin that provides the ability to use scenario based api mocking: for local development for protractor testing
MIT License
99 stars 26 forks source link

ngapimockid cookie is set too late #54

Open jpzwarte opened 6 years ago

jpzwarte commented 6 years ago

The problem i'm seeing is that the ngapimockid cookie is set too late, causing the calls to the (mock) backend to lack the cookie and always returning the default mocks, eventhough i'm calling selectScenario. See my analysis below.

When i add some console.log calls to my onPrepare method in protractor.conf and to the ng-apimock/lib/utils ngApimockRequest function, i see the following behavior:

PUT /ngapimock/mocks/defaults c3b27ce7-503a-4069-900c-60087b52471e

This is the setAllScenariosToDefault() call. The uuid is the ngapimockid value.

I then see the front-end doing a call: GET /teacher/groups undefined. The undefined here is the ngapimockid value.

After that, i get the console.log i put in the "hooker" code in .tmp/ngApimock/protractor.mock.js:

            require('hooker').hook(browser, 'get', {
                post: function (result) {
                    return result.then(function () {
                        // Since protractor 5.0.0 the addCookie is an object, see
                        // https://github.com/angular/protractor/blob/master/CHANGELOG.md#500
                        try {
                            console.log('setting ngapimockid cookie');
                            return browser.manage().addCookie({name: "ngapimockid", value: ngapimockid});
                        } catch (error) {
                            // Fallback protractor < 5.0.0
                            return browser.manage().addCookie('ngapimockid', ngapimockid);
                        }
                    });
                }
            });

When i add a browser.sleep(60000); in my it() and then refresh the browser, the ngapimockid cookie is present and passed to the mock server. I then get the appropriate mock back.

wswebcreation commented 6 years ago

@jpzwarte

Can you please share your code that sets the state? I'm using ng-apimock for more than 2 years now and don't have problems with it. My first guess would be a promise implementation on your side.

jpzwarte commented 6 years ago

@wswebcreation see https://gist.github.com/jpzwarte/a98149513b0f7437d3957d07abe79da8

jpzwarte commented 6 years ago

@wswebcreation @mdasberg the hack below works 💪

    // HACK: intercept the uuid call that ng-apimock makes in order to
    // get the ngapimockid. There's a bug where the cookie is set too late,
    // so fix that by doing it ourselves.
    const uuid = require('../node_modules/ng-apimock/node_modules/uuid'),
          originalFn = uuid.v4;

    let ngapimockId;
    uuid.v4 = function () {
      const result = ngapimockId = originalFn();

      return result;
    }

    // We need to be on a page in order to set the cookies
    browser.driver.get(browser.baseUrl);

    // Load ngApimock
    global['ngApimock'] = require('../.tmp/ngApimock/protractor.mock.js');
    beforeEach(() => global['ngApimock'].setAllScenariosToDefault());

    // Manually set ngapimockid cookie
    browser.manage().addCookie({ name: 'ngapimockid', value: ngapimockId });
wswebcreation commented 6 years ago

@jpzwarte

I never relied on the control-flow of Protractor, so I don't know if

    fit('should show a placeholder when no groups exist', () => {
      ngApimock.selectScenario('teacher-groups', 'empty');
      page.navigateTo();

      page.sleep(60000);
      expect(page.chooseExistingGroups.animation).toBeDisplayed();
      expect(page.chooseExistingGroups.pointers).toBeDisplayed();
    });

Works.

In my setup I'd always use this

    fit('should show a placeholder when no groups exist', async () => {
      await ngApimock.selectScenario('teacher-groups', 'empty');
      await page.navigateTo();

      expect(await page.chooseExistingGroups.animation).toBeDisplayed();
      expect(await page.chooseExistingGroups.pointers).toBeDisplayed();
    });

And this never gives problems

jpzwarte commented 6 years ago

I thought about this, for example i tried adding async/wait for the selectScenario call and a browser.sleep() before the page.navigateTo() but that didn't work. Anyway, i heard via some people that this issue may be fixed in another branch and may be backported. In the mean time i'll use my hack :)

wswebcreation commented 6 years ago

👍

Can we close the issue then?

jpzwarte commented 6 years ago

The bug report is still valid right? If so, i would keep it open to track progress.