Rob C
Rob C

Reputation: 737

TestCafe unable to use testController (t) outside of test run (e.g. as a conditional to skip a test)

I'm trying to check which browser we're running tests on, and then skip a test/fixture based on the result (as mentioned in this TestCafe Issue).

import { t } from 'testcafe';

fixture `test`
    .page('https://testcafe.devexpress.com')

if (t.browser.name.includes('Chrome')) {
  test('is Chrome?', async () => {
    console.log(t.browser.name);
    await t.expect(t.browser.name.includes('Chrome').ok();
  });
} else {
  test.skip('is Chrome?')
};

Results in...

ERROR Cannot prepare tests due to an error.

Cannot implicitly resolve the test run in the context of which the test controller action should be executed. Use test function's 't' argument instead.

Is there any way I can call the testObject (t) outside of the test?

Upvotes: 2

Views: 1433

Answers (2)

ds4940
ds4940

Reputation: 3672

The better solution, as mentioned in one of the comments in this question is to use the runner object in run your tests instead of the command line. Instead of passing the browser(s) as a CLI argument, you would pass it as an optional argument to a top-level script.

You would then read the browser variable from either the script parameter or the .testcaferc.json file.

You would need to tag all tests/fixtures with the browser(s) they apply to using meta data.

You then use the Runner.filter method to add a delegate that returns true if the browser in the meta data is equal to the browser variable in the top level script

var runner = testcafe.createRunner();
var browser = process.env.npm_package_config_browser || require("./testcaferc.json").browser;
var runner.filter((testName, fixtureName, fixturePath, testMeta, fixtureMeta) => {
    return fixtureMeta.browser === browser || testMeta.browser === browser ;
} 

Upvotes: 0

pavelsaman
pavelsaman

Reputation: 8322

I don't have a solution to exactly your question. But I think it's better to do it slightly differently, so the outcome will be the same, but the means to achieve it will differ a bit. Let me explain.

Wrapping test cases in if statements is, in my opinion, not a good idea. It mostly clutters test files so you don't only see test or fixture at the left side, but also if statements that make you stop when reading such files. It presents more complexity when you just want to scan a test file quickly from top to bottom.

The solution could be you introduce meta data to your test cases (could work well with fixtures as well).

test
    .meta({
        author: 'pavelsaman',
        creationDate: '16/12/2020',
        browser: 'chrome'
    })
    ('Test for Chrome', async t => {
    // test steps
});

Then you can execute only tests for Chrome like so:

$ testcafe --test-meta browser=chrome chrome

That's very much the same as what you wanted to achieve with the condition, but the code is a bit more readable.

In case you want to execute tests for both chrome and firefox, you can execute more commands:

$ testcafe --test-meta browser=chrome chrome
$ testcafe --test-meta browser=firefox firefox

or:

$ testcafe --test-meta browser=chrome chrome && testcafe --test-meta browser=firefox firefox

If your tests are in a pipeline, it would probably be done in two steps.

Upvotes: 4

Related Questions