0

I had a question that doesn't seem to be answered anywhere.

I am running tests from within my Express.js api. I set up a page that has a button and a field to enter a keyword intended to be used during a testcafe test. My endpoint I set up is /testcafe. But after sending a post request to /testcafe, there is a long delay while test runs and so my question is what is the best next step besides hanging?

Also, can my post request body, which contains the keyword, be directly used in a test like this? Keep in mind it's this pattern:

frontend -> POST request -> Express server -> /testcafe endpoint - test

My problem is after it reaches test, I currently have it attempting to call fetch from within the request logger. Is this right?

import { ClientFunction, Selector } from 'testcafe';
import { RequestLogger, RequestHook } from 'testcafe';
import zlib from 'zlib';
import fetch from 'isomorphic-unfetch';

const url = 'https://www.mysitetesturl.com/page';

class MyRequestHook extends RequestHook {
    constructor (requestFilterRules, responseEventConfigureOpts) {
        super(requestFilterRules, responseEventConfigureOpts);
    }

    onRequest (e) {
        console.log('in onRequest!')
        console.log('========================')
        console.log('Request Body')
        let buf = e._requestContext.reqBody
        console.log(buf.toLocaleString())
    }

    onResponse (e) {

    let buf = Buffer(e.body) 
    let unzippedBody = Buffer(zlib.gunzipSync(buf)) 
    let payload = unzippedBody.toLocaleString()
    fetch('http://myapiipaddress/api/testcafe',
        method: 'PUT',
        body: JSON.stringify(payload)
        )
        .then((err, doc) => {
            if(err) {
                console.log(err)
            } else {
                console.log(doc)
            }
        })   
    }
}

const myRequestHook = new MyRequestHook({
    url: url, 
    method:'get'},
    { 
        includeHeaders: true, 
        includeBody: true 
    }
);

fetch('http://myapiipaddress/api/testcafe',
    method: 'GET'
    )
    .then((err, doc) => {
        if(err) {
            console.log(err)
        } else {


            fixture`myfixture`
                .page(doc.url)
                .requestHooks(myRequestHook);

            test(`mytest`, async t => { 
            const inputField = Selector('input');

            await t
                await t
                .wait(5000)
                .typeText(inputField, doc.text)
                .wait(5000)

                }   
            );

        }
    })

Alex Skorkin
  • 4,264
  • 3
  • 25
  • 47
rom
  • 666
  • 2
  • 9
  • 31

1 Answers1

2

According to your scheme, you need to organize your code in a different way:

const createTestCafe = require('testcafe');
....

// Choose the necessary body parser for express application
// https://github.com/expressjs/body-parser
app.use(bodyParser.urlencoded({ extended: true })); 
...
app.post('/', function (req, res) {
    createTestCafe('localhost', 1337, 1338, void 0, true)
       .then(testcafe => {
           const runner = testcafe.createRunner();

           return runner
               .src('/tests')
               .browsers('chrome')
               .run();
        })
       .then(failedCount => {
          testcafe.close();
          res.end();
    });

})

mlosev
  • 5,130
  • 1
  • 19
  • 31
  • How can you use the request body in the test? I am sending JSON in req.body.keyword. How can I access req.body.keyword inside the test? I don't see the part where you are passing the request in so it can be used within the test like to type into a search bar. – rom May 21 '20 at 00:55
  • You can use [`process.env`](https://nodejs.org/api/process.html#process_process_env) or TestCafe [`clientScripts`](https://devexpress.github.io/testcafe/documentation/guides/advanced-guides/inject-client-scripts.html) functionality to pass `req.body.keyword` to a test. Please check answers from the following StackOverflow thread: [https://stackoverflow.com/questions/58075755/how-can-i-inject-parameters-into-a-testcaf%C3%A9-test](https://stackoverflow.com/questions/58075755/how-can-i-inject-parameters-into-a-testcaf%C3%A9-test) – aleks-pro May 22 '20 at 13:07
  • @aleks-pro I got process.env working but new problem. So, I just installed dotenv library and call .TypeText(inputField, process.env.KEYWORD). However, after a successful test with one keyword, when I run the next test with a new keyword (for example, 'frogs'), it uses the keyword from the FIRST test, even though I use a new keyword 'bacon' in the next test. It still types 'frogs'. Why is this? I have fs.writeFile writing the keywords to the .env file like so: KEYWORD=bacon. – rom May 24 '20 at 20:16
  • @rom, did you call the [`config`](https://www.npmjs.com/package/dotenv#config) method after `fs.writeFile` rewrote keywords in the `.env` file? And why don't you set `process.env.KEYWORD` explicitly in your code: `process.env.KEYWORD='bacon'`? This solution looks more simple to me. – aleks-pro May 26 '20 at 06:50
  • @aleks-pro I found where my mistake was. I was confusing dotenv library into this (I use dotenv and create process.env all the time but due to saving to .env file, this is different way to do it). I ended up realizing I could arbitrarily assign any values and any number of values to process.env and ended up going farther: process.env.KEYWORD = 'bacon', process.env.URL = 'http://urlhere', process.env.TACOS = 'on Tuesdays'. Thank you so much! – rom May 26 '20 at 23:45