Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the capability to execute a custom script before page initialization scripts #1739

Closed
AlexanderMoskovkin opened this issue Aug 29, 2017 · 32 comments · Fixed by #3880
Closed
Assignees
Labels
STATE: Auto-locked An issue has been automatically locked by the Lock bot. TYPE: enhancement The accepted proposal for future implementation.
Milestone

Comments

@AlexanderMoskovkin
Copy link
Contributor

AlexanderMoskovkin commented Aug 29, 2017

Are you requesting a feature or reporting a bug?

feature suggestion

What is the current behavior?

TestCafe executes a ClientFunction when the page is fully loaded.

What is the expected behavior?

Add ability to execute any client script in the browser before other page scripts.

Here are some use cases:
Catch JS errors and console output
Executing code in the browser before the page code evaluates

Proposed API:

import fs from 'fs';

const initializationScript = fs.readFileSync('./script.js').toString()

fixture `My fixture`
    .addScriptToEachPage(initializationScript);

test
    .addScriptToEachPage(initializationScript);

Feel free to vote for the feature if you consider it useful and please let us know about your use case for it.

@AlexanderMoskovkin AlexanderMoskovkin changed the title Add ability to execute a custom script before page initialization scripts Add the capability to execute a custom script before page initialization scripts Aug 29, 2017
@dimaip
Copy link

dimaip commented Aug 30, 2017

This feature is useful e.g. if you want to override console.log to spy on console output in your tests.

@CommanderXL
Copy link

Yes. This feature is good

@San4es
Copy link

San4es commented Sep 18, 2017

@AlexanderMoskovkin

I think that ClientFunction support will be useful for this feature:

test.addScriptToEachPage(ClientFunction(...));

@bisubus
Copy link

bisubus commented Mar 22, 2018

I would suggest to extend the proposal with several points made in #2234:

  • Multiple asset types (scripts, styles, fonts), useful for UI/visual regression testing or any cases that would require to apply test-related changes to application code otherwise

  • Multiple asset insertion positions (start and end of head and body), with end of document body as default value

  • 'Here and now' asset insertion position for fixture/test assets, a shortcut for t.eval () => { document.createElement... }, also accepts a ClientFunction

  • Local assets that are resolved from NPM module name or relative path, a shortcut for fs.readFileSync('require.resolve('module'), 'utf8') (currently included as is, no bundling or transpilation)

  • Remote CDN assets identified by URL

  • Fixture assets

  • Test assets

  • Global assets for entire test run (similar to Karma files) as runner and CLI options

Currently the framework has undocumented embeddingOptions runner method, it makes an asset (script or style) being served by TestCafe server, is available only on runner init but not in CLI. Another part of the process is internal testRun.injectable property that allows to push served script/style to <head>, it seems to be reachable in specs as t.testRun.injectable but is unavailable on runner init.

@craig-jennings
Copy link

This would also be helpful if certain local storage keys need to be set before the page loads.

@miherlosev
Copy link
Collaborator

Note: we already have build-in support for accessing console messages

@juliusgonawan
Copy link

any update for this enhancement?

@miherlosev
Copy link
Collaborator

Hi @juliusgonawan

Would you please describe a real life case for which you need this functionality?

@NickCis
Copy link
Contributor

NickCis commented Nov 6, 2018

@miherlosev
A real world escenario i've found is avoiding a service worker registration. If a service worker is registered without using https, chrome logs a console error which forces you to run testcafe with the -e flag. I'd like to run testcafe without ignoring Js Error messages.

Service worker are usually registered with an inline script:

<script>
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js');
}
</script>

So if i try to mock navigator.serviceWorker in the test, it will be mocked after the script has run.

@bitjoo
Copy link

bitjoo commented Nov 15, 2018

@miherlosev
A real world scenario is mine. I want to use PollyJS to record/mock some xhr or fetch requests. But to do so, I have to inject it into the page early. I tried it with ClientFunction, but it injects too late, so it missed some requests. An option to inject code as early as possible would be fine.

@AndreyBelym
Copy link
Contributor

@NickCis, @bitjoo - thank you for providing additional details. You can solve these issues by using RequestMock to handle specific page requests. Take a look at the following topics in the documentation:

For example, you can mock a service worker script for browsers that don't support this feature using the following code:

import { ClientFunction, RequestMock } from 'testcafe';

const supportsServiceWorkers = ClientFunction(() => 'serviceWorker' in navigator);

fixture `ServiceWorker`
    .page('http://my-site.com')
    .beforeEach(async t => {
         const canUseServiceWorkers = await supportsServiceWorkers();
       
         if (canUseServiceWorkers)
             return;

         await t.addRequestMocks(
             RequestMock()
                 .onRequest('http://my-site.com/service-worker.js')
                 .respond('');
         );
     });

@samsoft05
Copy link

samsoft05 commented Nov 25, 2018

@miherlosev One more use case is that. Since client scripts are loading after page load, we can not mock any setInterval, setTimout functions

@AndreyBelym AndreyBelym added this to New Features & APIs in Enhancements processing Mar 1, 2019
@AndreyBelym AndreyBelym moved this from New Features & APIs to Test API Suggestions in Enhancements processing Mar 1, 2019
@benmonro
Copy link
Contributor

benmonro commented Jun 5, 2019

@AlexKamaev would you guys accept a PR if I implement it?

@need-response-app need-response-app bot added the STATE: Need response An issue that requires a response or attention from the team. label Jun 5, 2019
@AlexSkorkin
Copy link
Collaborator

@benmonro, you are welcome to submit your PR. We will be happy to review it.

@need-response-app need-response-app bot removed the STATE: Need response An issue that requires a response or attention from the team. label Jun 6, 2019
@benmonro
Copy link
Contributor

hey all, started this PR w/ the changes: #3880
a bit unclear about where the tests for this should go, but hopefully the PR makes sense.

@need-response-app need-response-app bot added the STATE: Need response An issue that requires a response or attention from the team. label Jun 10, 2019
@AlexKamaev
Copy link
Contributor

@benmonro

We are discussing the API with the team. We'll prepare our full vision of the issue within a few days.
In addition, I want to mention that we'd like to support this feature not only for a configuration file, but for runner (as @miherlosev suggested in the #1739 (comment)), and fixture/test (as @AlexanderMoskovkin suggested in #1739 (comment))

@need-response-app need-response-app bot removed the STATE: Need response An issue that requires a response or attention from the team. label Jun 10, 2019
@miherlosev
Copy link
Collaborator

miherlosev commented Jun 13, 2019

After discussing with the team we introduce the following API principles for adding custom scripts to the tested page:

  • should be possible to add a custom script on several framework levels: Test API, Command line, Configuration and Runner
  • should be possible to specify one, list or array of the added custom scripts
  • should be possible to add a custom script to all or separate pages
  • should be possible to specify path or content of the added script

Client script initializers

String

fixture `Fixture`
    .clientScripts('asserts/helpers.js'); // path to file (relative or absolute)

Object with content

fixture `Fixture`
    .clientScripts({ content: 'var i = 0' '});

Object with path

fixture `Fixture`
     .clientScripts({ path: './assets/helpers.js' });

Object with page property (specified the pages for which the target script will be injected)

fixture `Fixture`
    .clientScripts({
        path: 'assets/helper.js'
        page: 'http://example.com'
    })

Object with 'module' property

fixture `Fixture`
    .clientScripts({ module: 'dom-utils' })

Possible arguments

fixutre `Fixture`.clientScripts('test1.js'); // single argument
fixture `Fixture.clientScripts('test1.js', 'test2.js'); // list of arguments
fixture `Fixture.clientScripts(['test1.js']); // array of arguments

API:

Test and fixture

fixture `My fixture`.clientScripts('test.js');
test.clientScripts('test.js');

Command line

testcafe chrome /tests --client-scripts asserts/jquery.js,mockDate.js

Configuration

{
    "clientScripts": ['wait-for-react-helper.js']
}

Runner

const runner = testcafe.createRunner();
        return runner
            .src(['tests/fixture1.js', 'tests/func/fixture3.js'])
            .browsers(['chrome', 'safari'])
            .clientScripts(['/assets/jquery.js'])
            .run();    

@benmonro
Copy link
Contributor

Would you also please consider a separate configuration for "beforeEach" that doesn't need to be set in each fixture? I had originally requested that and that issue was closed in favor of this one. Jest and mocha and other test runners have this feature as well for things like testing library add ons (like testcafe-testing-library) and it adds a nice way to centrally configure those things

@need-response-app need-response-app bot added the STATE: Need response An issue that requires a response or attention from the team. label Jun 13, 2019
@miherlosev
Copy link
Collaborator

Would you also please consider a separate configuration for "beforeEach" that doesn't need to be set in each fixture?

If you want to add a custom script for each fixture, use the clientScripts method/property at the Configuration, Command line and Runner levels.

For example, the following code will add /assets/jquery.js content to the tested page in each fixture.

const runner = testcafe.createRunner();
        return runner
            .src(['tests/fixture1.js', 'tests/func/fixture3.js'])
            .browsers(['chrome', 'safari'])
            .clientScripts(['/assets/jquery.js'])
            .run();    

@need-response-app need-response-app bot removed the STATE: Need response An issue that requires a response or attention from the team. label Jun 13, 2019
@benmonro
Copy link
Contributor

benmonro commented Jun 13, 2019 via email

@need-response-app need-response-app bot added the STATE: Need response An issue that requires a response or attention from the team. label Jun 13, 2019
@miherlosev
Copy link
Collaborator

miherlosev commented Jun 14, 2019

@benmonro
In this issue, we are discussing the capability to execute a custom script on the client side before page initialization scripts.
If you want to set up something on the server side, use the fixture.before hook.
If you have other questions that are not connected with the issue's subject, please create a separate issue regarding them. It will allow us to work on the problems and features more efficient.

@need-response-app need-response-app bot removed the STATE: Need response An issue that requires a response or attention from the team. label Jun 14, 2019
@benmonro
Copy link
Contributor

@miherlosev yes I did that but you closed that issue in favor of this one. #3857

fixture.before would still require a modification in each test figure file. I would like a way to globally set fixture.before I'm the way they jest or mocha let you set that as well.

@need-response-app need-response-app bot added the STATE: Need response An issue that requires a response or attention from the team. label Jun 14, 2019
@AlexKamaev AlexKamaev self-assigned this Jun 17, 2019
@AlexKamaev
Copy link
Contributor

@benmonro
We already have a suggestion to implement similar functionality. Please refer to it #745.
You are also welcome to share your thoughts there. I'd like to note that we do not know when we will be able to start working on that feature.
As for this ticket, let's continue discussing only the custom client script feature here.

@need-response-app need-response-app bot removed the STATE: Need response An issue that requires a response or attention from the team. label Jun 17, 2019
Enhancements processing automation moved this from Test API Suggestions to Closed Jul 24, 2019
miherlosev pushed a commit that referenced this issue Jul 24, 2019
* initial

* fix wrong rebase

* new logic for resolving relative paths (test api and others)

* refactoring

* fix tests

* provide error messages for uncaught errors occured in injected client scripts

* fix tests

* fix error messages

* fix server tests

* fix relative paths

* fix type definition

* prevent multiple method calls for clientScripts and requestHooks

* fix an error message during module loading

* specify execution order for clientScripts and requestHooks

* skip test

* skip test

* refix the test

* fix client scripts loading order and handle module path resolving errors
@lock
Copy link

lock bot commented Aug 3, 2019

This thread has been automatically locked since it is closed and there has not been any recent activity. Please open a new issue for related bugs or feature requests. We recommend you ask TestCafe API, usage and configuration inquiries on StackOverflow.

@lock lock bot added the STATE: Auto-locked An issue has been automatically locked by the Lock bot. label Aug 3, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Aug 3, 2019
kirovboris pushed a commit to kirovboris/testcafe-phoenix that referenced this issue Dec 18, 2019
)

* initial

* fix wrong rebase

* new logic for resolving relative paths (test api and others)

* refactoring

* fix tests

* provide error messages for uncaught errors occured in injected client scripts

* fix tests

* fix error messages

* fix server tests

* fix relative paths

* fix type definition

* prevent multiple method calls for clientScripts and requestHooks

* fix an error message during module loading

* specify execution order for clientScripts and requestHooks

* skip test

* skip test

* refix the test

* fix client scripts loading order and handle module path resolving errors
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
STATE: Auto-locked An issue has been automatically locked by the Lock bot. TYPE: enhancement The accepted proposal for future implementation.
Projects
No open projects
Development

Successfully merging a pull request may close this issue.