Feature: Downloading things from a website. Background: Given I set up a temporary download dir And I clean old downloads And I set downloads.remove_finished to -1 ## starting downloads Scenario: Clicking an unknown link When I set downloads.location.prompt to false And I open data/downloads/downloads.html And I run :click-element id download And I wait until the download is finished Then the downloaded file download.bin should exist Scenario: Using :download When I set downloads.location.prompt to false When I run :download http://localhost:(port)/data/downloads/download.bin And I wait until the download is finished Then the downloaded file download.bin should exist Scenario: Using :download with no URL When I set downloads.location.prompt to false And I open data/downloads/downloads.html And I run :download And I wait until the download is finished Then the downloaded file Simple downloads.html should exist Scenario: Using :download with no URL on an image When I set downloads.location.prompt to false And I open data/downloads/qutebrowser.png And I run :download And I wait until the download is finished Then the downloaded file qutebrowser.png should exist Scenario: Using hints When I set downloads.location.prompt to false And I open data/downloads/downloads.html And I hint with args "links download" and follow a And I wait until the download is finished Then the downloaded file download.bin should exist Scenario: Using rapid hints # We don't expect any prompts with rapid hinting even if this is true When I set downloads.location.prompt to true And I open data/downloads/downloads.html And I hint with args "--rapid links download" and follow a And I run :hint-follow s And I wait until the download download.bin is finished And I wait until the download download2.bin is finished Then the downloaded file download.bin should exist Then the downloaded file download2.bin should exist ## Regression tests Scenario: Downloading which redirects with closed tab (issue 889) When I set tabs.last_close to blank And I open data/downloads/issue889.html And I hint with args "links download" and follow a And I run :tab-close And I wait for "redirected: *" in the log Then no crash should happen Scenario: Downloading with error in closed tab (issue 889) When I set tabs.last_close to blank And I open data/downloads/issue889.html And I hint with args "links download" and follow s And I run :tab-close And I wait for the error "Download error: * - server replied: NOT FOUND" And I run :download-retry And I wait for the error "Download error: * - server replied: NOT FOUND" Then no crash should happen Scenario: Downloading a link without path information (issue 1243) When I set downloads.location.suggestion to filename And I set downloads.location.prompt to true And I open data/downloads/issue1243.html And I hint with args "links download" and follow a And I wait for "Asking question option=None text=* title='Save file to:'>, *" in the log Then the error "Download error: No handler found for qute://" should be shown And "NotFoundError while handling qute://* URL" should be logged Scenario: Downloading a data: link (issue 1214) When I set downloads.location.suggestion to filename And I set downloads.location.prompt to true And I open data/data_link.html And I hint with args "links download" and follow s And I wait for "Asking question option=None text=* title='Save file to:'>, *" in the log And I run :mode-leave Then no crash should happen Scenario: Aborting a download in a different window (issue 3378) When I set downloads.location.suggestion to filename And I set downloads.location.prompt to true And I open data/downloads/download.bin in a new window without waiting And I wait for "Asking question *" in the log And I run :window-only And I run :mode-leave Then no crash should happen Scenario: Closing window with downloads.remove_finished timeout (issue 1242) When I set downloads.remove_finished to 500 And I open data/downloads/download.bin in a new window without waiting And I wait until the download is finished And I run :close And I wait 0.5s Then no crash should happen Scenario: Quitting with finished downloads and confirm_quit=downloads (issue 846) Given I have a fresh instance When I set downloads.location.prompt to false And I set confirm_quit to [downloads] And I open data/downloads/download.bin without waiting And I wait until the download is finished And I run :close Then qutebrowser should quit # https://github.com/qutebrowser/qutebrowser/issues/2134 @qtwebengine_skip Scenario: Downloading, then closing a tab When I set downloads.location.prompt to false And I open about:blank And I open data/downloads/issue2134.html in a new tab # This needs to be a download connected to the tabs QNAM And I hint with args "links normal" and follow a And I wait for "fetch: * -> drip" in the log And I run :tab-close And I wait for "Download drip finished" in the log Then the downloaded file drip should be 128 bytes big Scenario: Downloading a file with spaces When I open data/downloads/download with spaces.bin without waiting And I wait until the download is finished Then the downloaded file download with spaces.bin should exist @qtwebkit_skip Scenario: Downloading a file with evil content-disposition header # Content-Disposition: download; filename=..%2Ffoo When I open response-headers?Content-Disposition=download;%20filename%3D..%252Ffoo without waiting And I wait until the download is finished Then the downloaded file ../foo should not exist And the downloaded file foo should exist @qtwebkit_skip Scenario: Downloading a file with evil content-disposition header 2 # Content-Disposition: download; filename=..%252Ffoo When I open response-headers?Content-Disposition=download;%20filename%3D..%25252Ffoo without waiting And I wait until the download is finished Then the downloaded file ../foo should not exist And the downloaded file ..%2Ffoo should exist @windows Scenario: Downloading a file to a reserved path When I set downloads.location.prompt to true And I open data/downloads/download.bin without waiting And I wait for "Asking question option=None text='Please enter a location for http://localhost:*/data/downloads/download.bin' title='Save file to:'>, *" in the log And I run :prompt-accept COM1 And I run :mode-leave Then the error "Invalid filename" should be shown @windows Scenario: Downloading a file to a drive-relative working directory When I set downloads.location.prompt to true And I open data/downloads/download.bin without waiting And I wait for "Asking question option=None text='Please enter a location for http://localhost:*/data/downloads/download.bin' title='Save file to:'>, *" in the log And I run :prompt-accept C:foobar And I run :mode-leave Then the error "Invalid filename" should be shown @windows Scenario: Downloading a file to a reserved path with :download When I run :download data/downloads/download.bin --dest=COM1 Then the error "Invalid target filename" should be shown @windows Scenario: Download a file to a drive-relative working directory with :download When I run :download data/downloads/download.bin --dest=C:foobar Then the error "Invalid target filename" should be shown ## :download-retry Scenario: Retrying a failed download When I run :download http://localhost:(port)/does-not-exist And I wait for the error "Download error: * - server replied: NOT FOUND" And I run :download-retry And I wait for the error "Download error: * - server replied: NOT FOUND" Then the requests should be: does-not-exist does-not-exist @flaky Scenario: Retrying with count When I run :download http://localhost:(port)/data/downloads/download.bin And I run :download http://localhost:(port)/does-not-exist And I wait for the error "Download error: * - server replied: NOT FOUND" And I run :download-retry with count 2 And I wait for the error "Download error: * - server replied: NOT FOUND" Then the requests should be: data/downloads/download.bin does-not-exist does-not-exist Scenario: Retrying with two failed downloads When I run :download http://localhost:(port)/does-not-exist And I run :download http://localhost:(port)/does-not-exist-2 And I wait for the error "Download error: * - server replied: NOT FOUND" And I wait for the error "Download error: * - server replied: NOT FOUND" And I run :download-retry And I wait for the error "Download error: * - server replied: NOT FOUND" Then the requests should be: does-not-exist does-not-exist-2 does-not-exist Scenario: Retrying a download which does not exist When I run :download-retry with count 42 Then the error "There's no download 42!" should be shown Scenario: Retrying a download which did not fail When I run :download http://localhost:(port)/data/downloads/download.bin And I wait until the download is finished And I run :download-retry with count 1 Then the error "Download 1 did not fail!" should be shown Scenario: Retrying a download with no failed ones When I run :download http://localhost:(port)/data/downloads/download.bin And I wait until the download is finished And I run :download-retry Then the error "No failed downloads!" should be shown ## Wrong invocations Scenario: :download --mhtml with a URL given When I run :download --mhtml http://foobar/ Then the error "Can only download the current page as mhtml." should be shown Scenario: :download with a filename and directory which doesn't exist When I run :download --dest (tmpdir)(dirsep)downloads(dirsep)somedir(dirsep)file http://localhost:(port)/data/downloads/download.bin And I wait for "Asking question option=None text='* does not exist. Create it?' title='Create directory?'>, *" in the log And I run :prompt-accept yes And I wait until the download is finished Then the downloaded file somedir/file should exist Scenario: :download with a directory which doesn't exist When I run :download --dest (tmpdir)(dirsep)downloads(dirsep)somedir(dirsep) http://localhost:(port)/data/downloads/download.bin And I wait for "Asking question option=None text='* does not exist. Create it?' title='Create directory?'>, *" in the log And I run :prompt-accept yes And I wait until the download is finished Then the downloaded file somedir/download.bin should exist ## mhtml downloads Scenario: Downloading as mhtml is available When I open data/title.html And I run :download --mhtml And I wait for "File successfully written." in the log Then the downloaded file Test title.mhtml should exist @qtwebengine_skip: QtWebEngine refuses to load this Scenario: Downloading as mhtml with non-ASCII headers When I open response-headers?Content-Type=text%2Fpl%C3%A4in And I run :download --mhtml --dest mhtml-response-headers.mhtml And I wait for "File successfully written." in the log Then the downloaded file mhtml-response-headers.mhtml should exist @qtwebengine_skip: https://github.com/qutebrowser/qutebrowser/issues/2288 Scenario: Overwriting existing mhtml file When I set downloads.location.prompt to true And I open data/title.html And I run :download --mhtml And I wait for "Asking question option=None text='Please enter a location for http://localhost:*/data/title.html' title='Save file to:'>, *" in the log And I run :prompt-accept And I wait for "File successfully written." in the log And I run :download --mhtml And I wait for "Asking question option=None text='Please enter a location for http://localhost:*/data/title.html' title='Save file to:'>, *" in the log And I run :prompt-accept And I wait for "Asking question option=None text='* already exists. Overwrite?' title='Overwrite existing file?'>, *" in the log And I run :prompt-accept yes And I wait for "File successfully written." in the log Then the downloaded file Test title.mhtml should exist @not_flatpak Scenario: Opening a mhtml download directly When I set downloads.location.prompt to true And I open / And I run :download --mhtml And I wait for the download prompt for "*" And I directly open the download Then "Opening *.mhtml* with [*python*]" should be logged ## :download-cancel Scenario: Cancelling a download When I run :download http://localhost:(port)/drip?numbytes=128&duration=5 And I run :download-cancel Then "cancelled" should be logged Scenario: Cancelling with no download and no ID When I run :download-cancel Then the error "There's no download!" should be shown Scenario: Cancelling a download which does not exist When I run :download-cancel with count 42 Then the error "There's no download 42!" should be shown Scenario: Cancelling a download which is already done When I open data/downloads/download.bin without waiting And I wait until the download is finished And I run :download-cancel Then the error "Download 1 is already done!" should be shown Scenario: Cancelling a download which is already done (with count) When I open data/downloads/download.bin without waiting And I wait until the download is finished And I run :download-cancel with count 1 Then the error "Download 1 is already done!" should be shown Scenario: Cancelling all downloads When I run :download http://localhost:(port)/drip?numbytes=128&duration=5 And I run :download http://localhost:(port)/drip?numbytes=128&duration=5 And I run :download-cancel --all Then "cancelled" should be logged And "cancelled" should be logged # https://github.com/qutebrowser/qutebrowser/issues/1535 @qtwebengine_todo: :download --mhtml is not implemented yet Scenario: Cancelling an MHTML download (issue 1535) When I open data/downloads/issue1535.html And I run :download --mhtml And I wait for "fetch: Py*.QtCore.QUrl('http://localhost:*/drip?numbytes=128&duration=2') -> drip" in the log And I run :download-cancel Then no crash should happen ## :download-remove / :download-clear Scenario: Removing a download When I open data/downloads/download.bin without waiting And I wait until the download is finished And I run :download-remove Then "Removed download *" should be logged Scenario: Removing a download which does not exist When I run :download-remove with count 42 Then the error "There's no download 42!" should be shown Scenario: Removing a download which is not done yet When I run :download http://localhost:(port)/drip?numbytes=128&duration=5 And I run :download-remove Then the error "Download 1 is not done!" should be shown Scenario: Removing a download which is not done yet (with count) When I run :download http://localhost:(port)/drip?numbytes=128&duration=5 And I run :download-remove with count 1 Then the error "Download 1 is not done!" should be shown Scenario: Removing all downloads via :download-remove When I open data/downloads/download.bin without waiting And I wait until the download is finished And I open data/downloads/download2.bin without waiting And I wait until the download is finished And I run :download-remove --all Then "Removed download *" should be logged Scenario: Removing all downloads via :download-clear When I open data/downloads/download.bin without waiting And I wait until the download is finished And I open data/downloads/download2.bin without waiting And I wait until the download is finished And I run :download-clear Then "Removed download *" should be logged ## :download-delete Scenario: Deleting a download When I open data/downloads/download.bin without waiting And I wait until the download is finished And I run :download-delete And I wait for "deleted download *" in the log Then the downloaded file download.bin should not exist Scenario: Deleting a download which does not exist When I run :download-delete with count 42 Then the error "There's no download 42!" should be shown Scenario: Deleting a download which is not done yet When I run :download http://localhost:(port)/drip?numbytes=128&duration=5 And I run :download-delete Then the error "Download 1 is not done!" should be shown Scenario: Deleting a download which is not done yet (with count) When I run :download http://localhost:(port)/drip?numbytes=128&duration=5 And I run :download-delete with count 1 Then the error "Download 1 is not done!" should be shown ## :download-open @not_flatpak Scenario: Opening a download When I open data/downloads/download.bin without waiting And I wait until the download is finished And I open the download Then "Opening *download.bin* with [*python*]" should be logged @not_flatpak Scenario: Opening a download with a placeholder When I open data/downloads/download.bin without waiting And I wait until the download is finished And I open the download with a placeholder Then "Opening *download.bin* with [*python*]" should be logged @not_flatpak Scenario: Opening a download with open_dispatcher set When I set a test python open_dispatcher And I open data/downloads/download.bin without waiting And I wait until the download is finished And I run :download-open Then "Opening *download.bin* with [*python*]" should be logged @not_flatpak Scenario: Opening a download with open_dispatcher set and override When I set downloads.open_dispatcher to cat And I open data/downloads/download.bin without waiting And I wait until the download is finished And I open the download Then "Opening *download.bin* with [*python*]" should be logged Scenario: Opening a download which does not exist When I run :download-open with count 42 Then the error "There's no download 42!" should be shown Scenario: Opening a download which is not done yet When I run :download http://localhost:(port)/drip?numbytes=128&duration=5 And I run :download-open Then the error "Download 1 is not done!" should be shown Scenario: Opening a download which is not done yet (with count) When I run :download http://localhost:(port)/drip?numbytes=128&duration=5 And I run :download-open with count 1 Then the error "Download 1 is not done!" should be shown ## opening a file directly (prompt-open-download) @not_flatpak Scenario: Opening a download directly When I set downloads.location.prompt to true And I open data/downloads/download.bin without waiting And I wait for the download prompt for "*" And I directly open the download And I wait until the download is finished Then "Opening *download.bin* with [*python*]" should be logged # https://github.com/qutebrowser/qutebrowser/issues/1728 Scenario: Cancelling a download that should be opened When I set downloads.location.prompt to true And I run :download http://localhost:(port)/drip?numbytes=128&duration=5 And I wait for the download prompt for "*" And I directly open the download And I run :download-cancel Then "* finished but not successful, not opening!" should be logged # https://github.com/qutebrowser/qutebrowser/issues/1725 @not_flatpak Scenario: Directly open a download with a very long filename When I set downloads.location.prompt to true And I open data/downloads/issue1725.html And I run :click-element id long-link And I wait for the download prompt for "*" And I directly open the download And I wait until the download is finished Then "Opening * with [*python*]" should be logged ## downloads.location.suggestion Scenario: downloads.location.suggestion = path When I set downloads.location.prompt to true And I set downloads.location.suggestion to path And I open data/downloads/download.bin without waiting Then the download prompt should be shown with "(tmpdir)/downloads/" Scenario: downloads.location.suggestion = filename When I set downloads.location.prompt to true And I set downloads.location.suggestion to filename And I open data/downloads/download.bin without waiting Then the download prompt should be shown with "download.bin" Scenario: downloads.location.suggestion = both When I set downloads.location.prompt to true And I set downloads.location.suggestion to both And I open data/downloads/download.bin without waiting Then the download prompt should be shown with "(tmpdir)/downloads/download.bin" ## downloads.location.remember Scenario: Remembering the last download directory When I set downloads.location.prompt to true And I set downloads.location.suggestion to both And I set downloads.location.remember to true And I open data/downloads/download.bin without waiting And I wait for the download prompt for "*/download.bin" And I run :prompt-accept (tmpdir)(dirsep)downloads(dirsep)subdir And I open data/downloads/download2.bin without waiting Then the download prompt should be shown with "(tmpdir)/downloads/subdir/download2.bin" Scenario: Clearing the last download directory when changing download location When I set downloads.location.prompt to true And I set downloads.location.suggestion to both And I set downloads.location.remember to true And I open data/downloads/download.bin without waiting And I wait for the download prompt for "*/download.bin" And I run :prompt-accept (tmpdir)(dirsep)downloads(dirsep)subdir And I run :set downloads.location.directory (tmpdir)(dirsep)downloads And I open data/downloads/download2.bin without waiting Then the download prompt should be shown with "(tmpdir)/downloads/download2.bin" Scenario: Not remembering the last download directory When I set downloads.location.prompt to true And I set downloads.location.suggestion to both And I set downloads.location.remember to false And I open data/downloads/download.bin without waiting And I wait for the download prompt for "(tmpdir)/downloads/download.bin" And I run :prompt-accept (tmpdir)(dirsep)downloads(dirsep)subdir And I open data/downloads/download2.bin without waiting Then the download prompt should be shown with "(tmpdir)/downloads/download2.bin" # https://github.com/qutebrowser/qutebrowser/issues/2173 @not_flatpak Scenario: Remembering the temporary download directory (issue 2173) When I set downloads.location.prompt to true And I set downloads.location.suggestion to both And I set downloads.location.remember to true And I open data/downloads/download.bin without waiting And I wait for the download prompt for "*" And I run :prompt-accept (tmpdir)(dirsep)downloads And I open data/downloads/download2.bin without waiting And I wait for the download prompt for "*" And I directly open the download And I open data/downloads/download.bin without waiting Then the download prompt should be shown with "(tmpdir)/downloads/download.bin" # Overwriting files Scenario: Not overwriting an existing file When I set downloads.location.prompt to false And I run :download http://localhost:(port)/data/downloads/download.bin And I wait until the download is finished And I run :download http://localhost:(port)/data/downloads/download2.bin --dest download.bin And I wait for "Entering mode KeyMode.yesno *" in the log And I run :prompt-accept no Then the downloaded file download.bin should be 1 bytes big Scenario: Overwriting an existing file When I set downloads.location.prompt to false And I run :download http://localhost:(port)/data/downloads/download.bin And I wait until the download is finished And I run :download http://localhost:(port)/data/downloads/download2.bin --dest download.bin And I wait for "Entering mode KeyMode.yesno *" in the log And I run :prompt-accept yes And I wait until the download is finished Then the downloaded file download.bin should be 2 bytes big @linux Scenario: Not overwriting a special file When I set downloads.location.prompt to false And I run :download http://localhost:(port)/data/downloads/download.bin --dest fifo And I wait for "Entering mode KeyMode.yesno *" in the log And I run :prompt-accept no Then the FIFO should still be a FIFO ## Redirects Scenario: Downloading with infinite redirect When I set downloads.location.prompt to false And I run :download http://localhost:(port)/redirect/21 --dest redirection Then the error "Download error: Too many redirects" should be shown And the downloaded file redirection should not exist Scenario: Downloading with redirect to itself When I set downloads.location.prompt to false And I run :download http://localhost:(port)/redirect-self Then the error "Download error: Too many redirects" should be shown And the downloaded file redirect-self should not exist Scenario: Downloading with absolute redirect When I set downloads.location.prompt to false And I run :download http://localhost:(port)/absolute-redirect And I wait until the download is finished Then the downloaded file absolute-redirect should exist Scenario: Downloading with relative redirect When I set downloads.location.prompt to false And I run :download http://localhost:(port)/relative-redirect And I wait until the download is finished Then the downloaded file relative-redirect should exist Scenario: Downloading with insecure redirect When I set downloads.location.prompt to false And I set content.tls.certificate_errors to load-insecurely And I download an SSL redirect page # First error is due to the load-insecurely value above Then the error "Certificate error: *The certificate is self-signed, and untrusted" should be shown And the error "Download error: Insecure redirect" should be shown And the downloaded file download.bin should not exist ## Other Scenario: Download without a content-size When I set downloads.location.prompt to false When I run :download http://localhost:(port)/content-size And I wait until the download is finished Then the downloaded file content-size should exist Scenario: Downloading to unwritable destination When the unwritable dir is unwritable And I set downloads.location.prompt to false And I run :download http://localhost:(port)/data/downloads/download.bin --dest (tmpdir)/downloads/unwritable Then the error "Download error: *" should be shown Scenario: Downloading 20MB file When I set downloads.location.prompt to false And I run :download http://localhost:(port)/twenty-mb And I wait until the download is finished Then the downloaded file twenty-mb should be 20971520 bytes big Scenario: Downloading 20MB file with late prompt confirmation When I set downloads.location.prompt to true And I run :download http://localhost:(port)/twenty-mb And I wait 1s And I run :prompt-accept And I wait until the download is finished Then the downloaded file twenty-mb should be 20971520 bytes big Scenario: Downloading invalid URL When I set downloads.location.prompt to false And I set url.auto_search to never And I run :download foo! Then the error "Invalid URL" should be shown Scenario: Downloading via pdfjs Given pdfjs is available When I set downloads.location.prompt to false And I set content.pdfjs to true And I open data/misc/test.pdf without waiting And I wait until PDF.js is ready And I run :click-element id download And I clear the log And I wait until the download is finished # We get viewer.html as name on QtWebKit... # Then the downloaded file test.pdf should exist Scenario: Answering a question for a cancelled download (#415) When I set downloads.location.prompt to true And I run :download http://localhost:(port)/data/downloads/download.bin And I wait for "Asking question option=None text=* title='Save file to:'>, *" in the log And I run :download http://localhost:(port)/data/downloads/download2.bin And I wait for "Asking question option=None text=* title='Save file to:'>, *" in the log And I run :download-cancel with count 2 And I run :prompt-accept And I wait until the download is finished Then the downloaded file download.bin should exist And the downloaded file download2.bin should not exist @qtwebengine_skip: We can't get the UA from the page there Scenario: user-agent when using :download When I open user-agent And I run :download --dest user-agent And I wait until the download is finished Then the downloaded file user-agent should contain Safari/ @qtwebengine_skip: We can't get the UA from the page there Scenario: user-agent when using hints When I open / And I run :hint links download And I run :hint-follow a And I wait until the download is finished Then the downloaded file user-agent should contain Safari/ @qtwebengine_skip: Handled by QtWebEngine, not by us Scenario: Downloading a "Internal server error" with disposition: inline (#2304) When I set downloads.location.prompt to false And I open 500-inline Then the error "Download error: *INTERNAL SERVER ERROR" should be shown ## External download path fileselector Scenario: Select download path When I set downloads.location.prompt to true And I setup a fake folder fileselector selecting "(tmpdir)(dirsep)downloads(dirsep)subdir" and writes to a temporary file And I open data/downloads/downloads.html And I run :click-element id download And I wait for the download prompt for "*" And I run :prompt-fileselect-external And I wait until the download is finished Then the downloaded file subdir/download.bin should exist Scenario: No download folder chosen When I set downloads.location.prompt to true And I set fileselect.folder.command to ['echo', '{}'] And I open data/downloads/downloads.html And I run :click-element id download And I wait for the download prompt for "*" And I run :prompt-fileselect-external Then the message "No folder chosen." should be shown And "No prompts left, hiding prompt container." should not be logged Scenario: Using :prompt-fileselect-external with other prompt When I open data/prompt/jsprompt.html And I run :click-element id button And I wait for "Asking question *" in the log And I run :prompt-fileselect-external Then the error "Can only launch external fileselect for FilenamePrompt, not LineEditPrompt" should be shown