{"action":"created","comment":{"url":"https://api.github.com/repos/plotly/dash/pulls/comments/217805694","pull_request_review_id":155614561,"id":217805694,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxNzgwNTY5NA==","diff_hunk":"@@ -532,3 +535,153 @@ def create_layout():\n \n         self.startServer(app)\n         time.sleep(0.5)\n+\n+    def test_with_custom_renderer(self):\n+        app = dash.Dash(__name__)\n+\n+        app.index_string = '''\n+        <!DOCTYPE html>\n+        <html>\n+            <head>\n+                {%metas%}\n+                <title>{%title%}</title>\n+                {%favicon%}\n+                {%css%}\n+            </head>\n+            <body>\n+                <div>Testing custom DashRenderer</div>\n+                {%app_entry%}\n+                <footer>\n+                    {%config%}\n+                    {%scripts%}\n+                    <script id=\"_dash-renderer\" type\"application/javascript\">\n+                        console.log('firing up a custom renderer!')\n+                        const renderer = new DashRenderer({\n+                            request_pre: () => {\n+                                var output = document.getElementById('output-pre')\n+                                if(output) {\n+                                    output.innerHTML = 'request_pre changed this text!';\n+                                }\n+                            },\n+                            request_post: () => {\n+                                var output = document.getElementById('output-post')\n+                                if(output) {\n+                                    output.innerHTML = 'request_post changed this text!';\n+                                }\n+                            }\n+                        })\n+                    </script>\n+                </footer>\n+                <div>With request hooks</div>\n+            </body>\n+        </html>\n+        '''\n+\n+        app.layout = html.Div([\n+            dcc.Input(\n+                id='input',\n+                value='initial value'\n+            ),\n+            html.Div(\n+                html.Div([\n+                    html.Div(id='output-1'),\n+                    html.Div(id='output-pre'),\n+                    html.Div(id='output-post')\n+                ])\n+            )\n+        ])\n+\n+        @app.callback(Output('output-1', 'children'), [Input('input', 'value')])\n+        def update_output(value):\n+            return value\n+\n+        self.startServer(app)\n+\n+        input1 = self.wait_for_element_by_id('input')\n+        input1.clear()\n+\n+        input1.send_keys('fire request hooks')\n+\n+        output1 = self.wait_for_element_by_id('output-1')\n+        output_pre = self.wait_for_element_by_id('output-pre')\n+        output_post = self.wait_for_element_by_id('output-post')\n+\n+        self.assertEqual('fire request hooks', output1.text)\n+        self.assertEqual('request_pre changed this text!', output_pre.text)\n+        self.assertEqual('request_post changed this text!', output_post.text)\n+        self.percy_snapshot(name='request-hooks')\n+\n+    def test_with_custom_renderer_interpolated(self):\n+        app = dash.Dash(__name__)\n+\n+        app.layout = html.Div([\n+            dcc.Input(\n+                id='input',\n+                value='initial value'\n+            ),\n+            html.Div(\n+                html.Div([\n+                    html.Div(id='output-1'),\n+                    html.Div(id='output-pre'),\n+                    html.Div(id='output-post')\n+                ])\n+            )\n+        ])\n+\n+        @app.callback(Output('output-1', 'children'), [Input('input', 'value')])\n+        def update_output(value):\n+            return value\n+\n+        scripts = app._generate_scripts_html()\n+        css = app._generate_css_dist_html()\n+        config = app._generate_config_html()\n+        metas = app._generate_meta_html()\n+        title = \"test custom renderer on interpolated_index\"\n+        favicon = ''\n+        _app_entry = '''\n+        <div id=\"react-entry-point\">\n+            <div class=\"_dash-loading\">\n+                Loading...\n+            </div>\n+        </div>\n+        '''\n+        renderer = '''\n+        <script id=\"_dash-renderer\" type\"application/javascript\">\n+            console.log('firing up a custom renderer!')\n+            const renderer = new DashRenderer({\n+                request_pre: () => {\n+                    var output = document.getElementById('output-pre')\n+                    if(output) {\n+                        output.innerHTML = 'request_pre changed this text!';\n+                    }\n+                },\n+                request_post: () => {\n+                    var output = document.getElementById('output-post')\n+                    if(output) {\n+                        output.innerHTML = 'request_post changed this text!';\n+                    }\n+                }\n+            })\n+        </script>\n+        '''\n+\n+        index = app.interpolate_index(\n+            metas=metas, title=title, css=css, config=config,\n+            scripts=scripts, app_entry=_app_entry, favicon=favicon,\n+            renderer=renderer)\n+\n+        self.startServer(app)\n+\n+        input1 = self.wait_for_element_by_id('input')\n+        input1.clear()\n+\n+        input1.send_keys('fire request hooks')\n+\n+        output1 = self.wait_for_element_by_id('output-1')","path":"tests/test_integration.py","position":95,"original_position":170,"commit_id":"2a0c922e086b4ba7a951c483a09743d1903a8887","original_commit_id":"2a0c922e086b4ba7a951c483a09743d1903a8887","user":{"login":"chriddyp","id":1280389,"node_id":"MDQ6VXNlcjEyODAzODk=","avatar_url":"https://avatars3.githubusercontent.com/u/1280389?v=4","gravatar_id":"","url":"https://api.github.com/users/chriddyp","html_url":"https://github.com/chriddyp","followers_url":"https://api.github.com/users/chriddyp/followers","following_url":"https://api.github.com/users/chriddyp/following{/other_user}","gists_url":"https://api.github.com/users/chriddyp/gists{/gist_id}","starred_url":"https://api.github.com/users/chriddyp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chriddyp/subscriptions","organizations_url":"https://api.github.com/users/chriddyp/orgs","repos_url":"https://api.github.com/users/chriddyp/repos","events_url":"https://api.github.com/users/chriddyp/events{/privacy}","received_events_url":"https://api.github.com/users/chriddyp/received_events","type":"User","site_admin":false},"body":"these items should already be on the page at this point, so I don't think that there will be any waiting that will happen. However, `send_keys` will fire off several async callback functions, so you will likely need to _wait_ for `output1.text` text to equal \"fire request hooks\". In some other dash projects, we had a utility `wait_for_text_to_equal` that would be good here, or there might be something native in selenium","created_at":"2018-09-14T18:36:46Z","updated_at":"2018-09-14T18:36:46Z","html_url":"https://github.com/plotly/dash/pull/367#discussion_r217805694","pull_request_url":"https://api.github.com/repos/plotly/dash/pulls/367","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/plotly/dash/pulls/comments/217805694"},"html":{"href":"https://github.com/plotly/dash/pull/367#discussion_r217805694"},"pull_request":{"href":"https://api.github.com/repos/plotly/dash/pulls/367"}}},"pull_request":{"url":"https://api.github.com/repos/plotly/dash/pulls/367","id":213336913,"node_id":"MDExOlB1bGxSZXF1ZXN0MjEzMzM2OTEz","html_url":"https://github.com/plotly/dash/pull/367","diff_url":"https://github.com/plotly/dash/pull/367.diff","patch_url":"https://github.com/plotly/dash/pull/367.patch","issue_url":"https://api.github.com/repos/plotly/dash/issues/367","number":367,"state":"open","locked":false,"title":"Standalone dash renderer (for custom hooks)","user":{"login":"valentijnnieman","id":6509622,"node_id":"MDQ6VXNlcjY1MDk2MjI=","avatar_url":"https://avatars2.githubusercontent.com/u/6509622?v=4","gravatar_id":"","url":"https://api.github.com/users/valentijnnieman","html_url":"https://github.com/valentijnnieman","followers_url":"https://api.github.com/users/valentijnnieman/followers","following_url":"https://api.github.com/users/valentijnnieman/following{/other_user}","gists_url":"https://api.github.com/users/valentijnnieman/gists{/gist_id}","starred_url":"https://api.github.com/users/valentijnnieman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/valentijnnieman/subscriptions","organizations_url":"https://api.github.com/users/valentijnnieman/orgs","repos_url":"https://api.github.com/users/valentijnnieman/repos","events_url":"https://api.github.com/users/valentijnnieman/events{/privacy}","received_events_url":"https://api.github.com/users/valentijnnieman/received_events","type":"User","site_admin":false},"body":"This enables the `dash-renderer` to be called as a standalone class, so that we can pass config objects to it. \r\n\r\nDepends on [this PR that enables dash-renderer to be a standalone class](https://github.com/plotly/dash-renderer/pull/75) to be merged (also see this PR for an example of how to use a custom `DashRenderer` instance).","created_at":"2018-09-05T15:29:46Z","updated_at":"2018-09-14T18:36:46Z","closed_at":null,"merged_at":null,"merge_commit_sha":"53a6c56defb72bd464be99eac9a06982ad2bf5b2","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":958241929,"node_id":"MDU6TGFiZWw5NTgyNDE5Mjk=","url":"https://api.github.com/repos/plotly/dash/labels/Sponsored","name":"Sponsored","color":"97d8ef","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/plotly/dash/pulls/367/commits","review_comments_url":"https://api.github.com/repos/plotly/dash/pulls/367/comments","review_comment_url":"https://api.github.com/repos/plotly/dash/pulls/comments{/number}","comments_url":"https://api.github.com/repos/plotly/dash/issues/367/comments","statuses_url":"https://api.github.com/repos/plotly/dash/statuses/2a0c922e086b4ba7a951c483a09743d1903a8887","head":{"label":"plotly:standalone_dash-renderer","ref":"standalone_dash-renderer","sha":"2a0c922e086b4ba7a951c483a09743d1903a8887","user":{"login":"plotly","id":5997976,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU5OTc5NzY=","avatar_url":"https://avatars2.githubusercontent.com/u/5997976?v=4","gravatar_id":"","url":"https://api.github.com/users/plotly","html_url":"https://github.com/plotly","followers_url":"https://api.github.com/users/plotly/followers","following_url":"https://api.github.com/users/plotly/following{/other_user}","gists_url":"https://api.github.com/users/plotly/gists{/gist_id}","starred_url":"https://api.github.com/users/plotly/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/plotly/subscriptions","organizations_url":"https://api.github.com/users/plotly/orgs","repos_url":"https://api.github.com/users/plotly/repos","events_url":"https://api.github.com/users/plotly/events{/privacy}","received_events_url":"https://api.github.com/users/plotly/received_events","type":"Organization","site_admin":false},"repo":{"id":33702544,"node_id":"MDEwOlJlcG9zaXRvcnkzMzcwMjU0NA==","name":"dash","full_name":"plotly/dash","owner":{"login":"plotly","id":5997976,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU5OTc5NzY=","avatar_url":"https://avatars2.githubusercontent.com/u/5997976?v=4","gravatar_id":"","url":"https://api.github.com/users/plotly","html_url":"https://github.com/plotly","followers_url":"https://api.github.com/users/plotly/followers","following_url":"https://api.github.com/users/plotly/following{/other_user}","gists_url":"https://api.github.com/users/plotly/gists{/gist_id}","starred_url":"https://api.github.com/users/plotly/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/plotly/subscriptions","organizations_url":"https://api.github.com/users/plotly/orgs","repos_url":"https://api.github.com/users/plotly/repos","events_url":"https://api.github.com/users/plotly/events{/privacy}","received_events_url":"https://api.github.com/users/plotly/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/plotly/dash","description":"Interactive, Reactive Web Apps for Python. Dash Is Productive™","fork":false,"url":"https://api.github.com/repos/plotly/dash","forks_url":"https://api.github.com/repos/plotly/dash/forks","keys_url":"https://api.github.com/repos/plotly/dash/keys{/key_id}","collaborators_url":"https://api.github.com/repos/plotly/dash/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/plotly/dash/teams","hooks_url":"https://api.github.com/repos/plotly/dash/hooks","issue_events_url":"https://api.github.com/repos/plotly/dash/issues/events{/number}","events_url":"https://api.github.com/repos/plotly/dash/events","assignees_url":"https://api.github.com/repos/plotly/dash/assignees{/user}","branches_url":"https://api.github.com/repos/plotly/dash/branches{/branch}","tags_url":"https://api.github.com/repos/plotly/dash/tags","blobs_url":"https://api.github.com/repos/plotly/dash/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/plotly/dash/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/plotly/dash/git/refs{/sha}","trees_url":"https://api.github.com/repos/plotly/dash/git/trees{/sha}","statuses_url":"https://api.github.com/repos/plotly/dash/statuses/{sha}","languages_url":"https://api.github.com/repos/plotly/dash/languages","stargazers_url":"https://api.github.com/repos/plotly/dash/stargazers","contributors_url":"https://api.github.com/repos/plotly/dash/contributors","subscribers_url":"https://api.github.com/repos/plotly/dash/subscribers","subscription_url":"https://api.github.com/repos/plotly/dash/subscription","commits_url":"https://api.github.com/repos/plotly/dash/commits{/sha}","git_commits_url":"https://api.github.com/repos/plotly/dash/git/commits{/sha}","comments_url":"https://api.github.com/repos/plotly/dash/comments{/number}","issue_comment_url":"https://api.github.com/repos/plotly/dash/issues/comments{/number}","contents_url":"https://api.github.com/repos/plotly/dash/contents/{+path}","compare_url":"https://api.github.com/repos/plotly/dash/compare/{base}...{head}","merges_url":"https://api.github.com/repos/plotly/dash/merges","archive_url":"https://api.github.com/repos/plotly/dash/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/plotly/dash/downloads","issues_url":"https://api.github.com/repos/plotly/dash/issues{/number}","pulls_url":"https://api.github.com/repos/plotly/dash/pulls{/number}","milestones_url":"https://api.github.com/repos/plotly/dash/milestones{/number}","notifications_url":"https://api.github.com/repos/plotly/dash/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/plotly/dash/labels{/name}","releases_url":"https://api.github.com/repos/plotly/dash/releases{/id}","deployments_url":"https://api.github.com/repos/plotly/dash/deployments","created_at":"2015-04-10T01:53:08Z","updated_at":"2018-09-14T12:38:30Z","pushed_at":"2018-09-14T18:13:37Z","git_url":"git://github.com/plotly/dash.git","ssh_url":"git@github.com:plotly/dash.git","clone_url":"https://github.com/plotly/dash.git","svn_url":"https://github.com/plotly/dash","homepage":"https://plot.ly/products/dash","size":2233,"stargazers_count":6060,"watchers_count":6060,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":587,"mirror_url":null,"archived":false,"open_issues_count":100,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":587,"open_issues":100,"watchers":6060,"default_branch":"master"}},"base":{"label":"plotly:master","ref":"master","sha":"78b84cada4927bfa02bc53c44cb765880eafe2c5","user":{"login":"plotly","id":5997976,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU5OTc5NzY=","avatar_url":"https://avatars2.githubusercontent.com/u/5997976?v=4","gravatar_id":"","url":"https://api.github.com/users/plotly","html_url":"https://github.com/plotly","followers_url":"https://api.github.com/users/plotly/followers","following_url":"https://api.github.com/users/plotly/following{/other_user}","gists_url":"https://api.github.com/users/plotly/gists{/gist_id}","starred_url":"https://api.github.com/users/plotly/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/plotly/subscriptions","organizations_url":"https://api.github.com/users/plotly/orgs","repos_url":"https://api.github.com/users/plotly/repos","events_url":"https://api.github.com/users/plotly/events{/privacy}","received_events_url":"https://api.github.com/users/plotly/received_events","type":"Organization","site_admin":false},"repo":{"id":33702544,"node_id":"MDEwOlJlcG9zaXRvcnkzMzcwMjU0NA==","name":"dash","full_name":"plotly/dash","owner":{"login":"plotly","id":5997976,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU5OTc5NzY=","avatar_url":"https://avatars2.githubusercontent.com/u/5997976?v=4","gravatar_id":"","url":"https://api.github.com/users/plotly","html_url":"https://github.com/plotly","followers_url":"https://api.github.com/users/plotly/followers","following_url":"https://api.github.com/users/plotly/following{/other_user}","gists_url":"https://api.github.com/users/plotly/gists{/gist_id}","starred_url":"https://api.github.com/users/plotly/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/plotly/subscriptions","organizations_url":"https://api.github.com/users/plotly/orgs","repos_url":"https://api.github.com/users/plotly/repos","events_url":"https://api.github.com/users/plotly/events{/privacy}","received_events_url":"https://api.github.com/users/plotly/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/plotly/dash","description":"Interactive, Reactive Web Apps for Python. Dash Is Productive™","fork":false,"url":"https://api.github.com/repos/plotly/dash","forks_url":"https://api.github.com/repos/plotly/dash/forks","keys_url":"https://api.github.com/repos/plotly/dash/keys{/key_id}","collaborators_url":"https://api.github.com/repos/plotly/dash/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/plotly/dash/teams","hooks_url":"https://api.github.com/repos/plotly/dash/hooks","issue_events_url":"https://api.github.com/repos/plotly/dash/issues/events{/number}","events_url":"https://api.github.com/repos/plotly/dash/events","assignees_url":"https://api.github.com/repos/plotly/dash/assignees{/user}","branches_url":"https://api.github.com/repos/plotly/dash/branches{/branch}","tags_url":"https://api.github.com/repos/plotly/dash/tags","blobs_url":"https://api.github.com/repos/plotly/dash/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/plotly/dash/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/plotly/dash/git/refs{/sha}","trees_url":"https://api.github.com/repos/plotly/dash/git/trees{/sha}","statuses_url":"https://api.github.com/repos/plotly/dash/statuses/{sha}","languages_url":"https://api.github.com/repos/plotly/dash/languages","stargazers_url":"https://api.github.com/repos/plotly/dash/stargazers","contributors_url":"https://api.github.com/repos/plotly/dash/contributors","subscribers_url":"https://api.github.com/repos/plotly/dash/subscribers","subscription_url":"https://api.github.com/repos/plotly/dash/subscription","commits_url":"https://api.github.com/repos/plotly/dash/commits{/sha}","git_commits_url":"https://api.github.com/repos/plotly/dash/git/commits{/sha}","comments_url":"https://api.github.com/repos/plotly/dash/comments{/number}","issue_comment_url":"https://api.github.com/repos/plotly/dash/issues/comments{/number}","contents_url":"https://api.github.com/repos/plotly/dash/contents/{+path}","compare_url":"https://api.github.com/repos/plotly/dash/compare/{base}...{head}","merges_url":"https://api.github.com/repos/plotly/dash/merges","archive_url":"https://api.github.com/repos/plotly/dash/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/plotly/dash/downloads","issues_url":"https://api.github.com/repos/plotly/dash/issues{/number}","pulls_url":"https://api.github.com/repos/plotly/dash/pulls{/number}","milestones_url":"https://api.github.com/repos/plotly/dash/milestones{/number}","notifications_url":"https://api.github.com/repos/plotly/dash/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/plotly/dash/labels{/name}","releases_url":"https://api.github.com/repos/plotly/dash/releases{/id}","deployments_url":"https://api.github.com/repos/plotly/dash/deployments","created_at":"2015-04-10T01:53:08Z","updated_at":"2018-09-14T12:38:30Z","pushed_at":"2018-09-14T18:13:37Z","git_url":"git://github.com/plotly/dash.git","ssh_url":"git@github.com:plotly/dash.git","clone_url":"https://github.com/plotly/dash.git","svn_url":"https://github.com/plotly/dash","homepage":"https://plot.ly/products/dash","size":2233,"stargazers_count":6060,"watchers_count":6060,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":587,"mirror_url":null,"archived":false,"open_issues_count":100,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":587,"open_issues":100,"watchers":6060,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/plotly/dash/pulls/367"},"html":{"href":"https://github.com/plotly/dash/pull/367"},"issue":{"href":"https://api.github.com/repos/plotly/dash/issues/367"},"comments":{"href":"https://api.github.com/repos/plotly/dash/issues/367/comments"},"review_comments":{"href":"https://api.github.com/repos/plotly/dash/pulls/367/comments"},"review_comment":{"href":"https://api.github.com/repos/plotly/dash/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/plotly/dash/pulls/367/commits"},"statuses":{"href":"https://api.github.com/repos/plotly/dash/statuses/2a0c922e086b4ba7a951c483a09743d1903a8887"}},"author_association":"NONE"}}
{"actor":{"display_login":"chriddyp"}}