diff --git a/.circleci/config.yml b/.circleci/config.yml index 97a0e6ed37..4f05b83127 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -211,16 +211,10 @@ jobs: # runs the frontend tests. - *upload_coverage_report - - store_artifacts: - path: ./var/casper/ - destination: casper - - store_artifacts: path: ./var/puppeteer/ destination: puppeteer - - store_test_results: - path: ./var/xunit-test-results/casper/ - *notify_failure_status "focal-backend": diff --git a/.eslintrc.json b/.eslintrc.json index e80e94e889..21378981dd 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -343,7 +343,6 @@ "files": ["frontend_tests/**"], "globals": { "assert": false, - "casper": false, "document": false, "set_global": false, "window": false, @@ -355,11 +354,7 @@ } }, { - "files": [ - "frontend_tests/casper_lib/**", - "frontend_tests/casper_tests/**", - "tools/debug-require.js" - ], + "files": ["tools/debug-require.js"], "env": { "browser": true, "es2020": false diff --git a/frontend_tests/casper_lib/.gitignore b/frontend_tests/casper_lib/.gitignore deleted file mode 100644 index d887e75259..0000000000 --- a/frontend_tests/casper_lib/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/server.log -/test_credentials.js diff --git a/frontend_tests/casper_lib/common.js b/frontend_tests/casper_lib/common.js deleted file mode 100644 index b61d3634ca..0000000000 --- a/frontend_tests/casper_lib/common.js +++ /dev/null @@ -1,512 +0,0 @@ -"use strict"; - -var util = require("util"); - -var test_credentials = require("../../var/casper/test_credentials.js").test_credentials; - -casper.options.clientScripts.push("frontend_tests/casper_lib/polyfill.js"); - -function timestamp() { - return new Date().getTime(); -} - -// The timestamp of the last message send or get_events result. -var last_send_or_update = -1; - -function log_in() { - var credentials = test_credentials.default_user; - - casper.test.info("Logging in"); - casper.fill( - 'form[action^="/accounts/login/"]', - { - username: credentials.username, - password: credentials.password, - }, - true /* submit form */ - ); -} - -exports.init_viewport = function () { - casper.options.viewportSize = {width: 1280, height: 1024}; -}; - -// This function should always be enclosed within a then() otherwise -// it might not exist on casper object. -exports.wait_for_text = function (selector, text, then, onTimeout, timeout) { - casper.waitForSelector( - selector, - function _then() { - casper.waitFor( - function _check() { - var content = casper.fetchText(selector); - if (util.isRegExp(text)) { - return text.test(content); - } - return content.indexOf(text) !== -1; - }, - then, - onTimeout, - timeout - ); - }, - onTimeout, - timeout - ); -}; - -exports.initialize_casper = function () { - if (casper.zulip_initialized !== undefined) { - return; - } - casper.zulip_initialized = true; - // These initialization steps will fail if they run before - // casper.start has been called. - - // Fail if we get a JavaScript error in the page's context. - // Based on the example at https://phantomjs.org/release-1.5.html - // - // casper.on('error') doesn't work (it never gets called) so we - // set this at the PhantomJS level. - casper.page.onError = function (msg, trace) { - casper.test.error(msg); - casper.echo("Traceback:"); - trace.forEach(function (item) { - casper.echo(" " + item.file + ":" + item.line); - }); - casper.exit(1); - }; - - // Capture screens from all failures - var casper_failure_count = 1; - casper.test.on("fail", function failure() { - if (casper_failure_count <= 10) { - casper.capture("var/casper/casper-failure" + casper_failure_count + ".png"); - casper_failure_count += 1; - } - }); - - // Update last_send_or_update whenever get_events returns. - casper.on("resource.received", function (resource) { - if (/\/json\/get_events/.test(resource.url)) { - last_send_or_update = timestamp(); - } - }); - - casper.on("load.finished", function () { - casper.test.info("page load finished"); - }); - - casper.evaluate(function () { - window.localStorage.clear(); - }); - - // This captures console messages from the app. - casper.on("remote.message", function (msg) { - casper.echo("app console: " + msg); - }); -}; - -exports.start_and_log_in = function () { - var log_in_url = "http://zulip.zulipdev.com:9981/accounts/login/"; - exports.init_viewport(); - casper.start(log_in_url, function () { - exports.initialize_casper(); - log_in(); - }); -}; - -exports.then_click = function (selector) { - casper.then(function () { - casper.waitUntilVisible(selector, function () { - casper.click(selector); - }); - }); -}; - -exports.then_log_in = function () { - casper.then(function () { - log_in(); - }); -}; - -exports.then_log_out = function () { - var menu_selector = "#settings-dropdown"; - var logout_selector = 'a[href="#logout"]'; - - casper.waitUntilVisible(menu_selector, function () { - casper.click(menu_selector); - - casper.waitUntilVisible(logout_selector, function () { - casper.test.info("Logging out"); - casper.click(logout_selector); - }); - }); - casper.waitUntilVisible(".login-page-container", function () { - casper.test.assertUrlMatch(/accounts\/login\/$/); - casper.test.info("Logged out"); - }); -}; - -// Put the specified string into the field_selector, then -// select the menu item matching item by typing str. -exports.select_item_via_typeahead = function (field_selector, str, item) { - casper.then(function () { - casper.test.info("Looking in " + field_selector + " to select " + str + ", " + item); - - casper.evaluate( - function (field_selector, str, item) { - // Set the value and then send a bogus keyup event to trigger - // the typeahead. - $(field_selector) - .trigger("focus") - .val(str) - .trigger($.Event("keyup", {which: 0})); - - // You might think these steps should be split by casper.then, - // but apparently that's enough to make the typeahead close (??), - // but not the first time. - - // Trigger the typeahead. - // Reaching into the guts of Bootstrap Typeahead like this is not - // great, but I found it very hard to do it any other way. - - var tah = $(field_selector).data().typeahead; - tah.mouseenter({ - currentTarget: $('.typeahead:visible li:contains("' + item + '")')[0], - }); - tah.select(); - }, - {field_selector: field_selector, str: str, item: item} - ); - }); -}; - -exports.check_form = function (form_selector, expected, test_name) { - var values = casper.getFormValues(form_selector); - var k; - for (k in expected) { - if (Object.prototype.hasOwnProperty.call(expected, k)) { - casper.test.assertEqual( - values[k], - expected[k], - test_name ? test_name + ": " + k : undefined - ); - } - } -}; - -exports.wait_for_message_fully_processed = function (content) { - casper.waitFor(function () { - return casper.evaluate( - function (content) { - /* - The tricky part about making sure that - a message has actually been fully processed - is that we'll "locally echo" the message - first on the client. Until the server - actually acks the message, the message will - have a temporary id and will not have all - the normal message controls. - - For the Casper tests, we want to avoid all - the edge cases with locally echoed messages. - - In order to make sure a message is processed, - we use internals to determine the following: - - has message_list even been updated with - the message with out content? - - has the locally_echoed flag been cleared? - - But for the final steps we look at the - actual DOM (via JQuery): - - is it visible? - - does it look to have been - re-rendered based on server info? - */ - var last_msg = current_msg_list.last(); - - if (last_msg.raw_content !== content) { - return false; - } - - if (last_msg.locally_echoed) { - return false; - } - - var row = rows.last_visible(); - - if (rows.id(row) !== last_msg.id) { - return false; - } - - /* - Make sure the message is completely - re-rendered from its original "local echo" - version by looking for the star icon. We - don't add the star icon until the server - responds. - */ - return row.find(".star").length === 1; - }, - {content: content} - ); - }); -}; - -exports.turn_off_press_enter_to_send = function () { - var enter_send_selector = "#enter_sends"; - casper.waitForSelector(enter_send_selector); - - var is_checked = casper.evaluate(function (enter_send_selector) { - return document.querySelector(enter_send_selector).checked; - }, enter_send_selector); - - if (is_checked) { - casper.click(enter_send_selector); - } -}; - -exports.pm_recipient = { - set: function (recip) { - casper.evaluate( - function (recipient) { - $("#private_message_recipient") - .text(recipient) - .trigger({type: "keydown", keyCode: 13}); - }, - {recipient: recip} - ); - }, - - expect: function (expected_value) { - var displayed_recipients = casper.evaluate(function () { - return compose_state.private_message_recipient(); - }); - casper.test.assertEquals(displayed_recipients, expected_value); - }, -}; - -// Wait for any previous send to finish, then send a message. -exports.then_send_message = function (type, params) { - // If a message is outside the view, we will skip - // validation later. - var outside_view = params.outside_view; - delete params.outside_view; - - casper.then(function () { - casper.waitForSelector("#compose-send-button:enabled"); - casper.waitForSelector("#compose-textarea"); - }); - - casper.then(function () { - if (type === "stream") { - casper.page.sendEvent("keypress", "c"); - } else if (type === "private") { - casper.page.sendEvent("keypress", "x"); - } else { - casper.test.assertTrue(false, "send_message got valid message type"); - } - - exports.pm_recipient.set(params.recipient); - delete params.recipient; - - if (params.stream) { - params.stream_message_recipient_stream = params.stream; - delete params.stream; - } - - if (params.subject) { - params.stream_message_recipient_topic = params.subject; - delete params.subject; - } - - casper.fill('form[action^="/json/messages"]', params); - - exports.turn_off_press_enter_to_send(); - - casper.then(function () { - casper.click("#compose-send-button"); - }); - }); - - casper.then(function () { - casper.waitFor(function emptyComposeBox() { - return casper.getFormValues('form[action^="/json/messages"]').content === ""; - }); - if (!outside_view) { - exports.wait_for_message_fully_processed(params.content); - } - casper.evaluate(function () { - compose_actions.cancel(); - }); - }); - - casper.then(function () { - last_send_or_update = timestamp(); - }); -}; - -// Get message headings (recipient rows) and bodies out of the DOM. -// casper.evaluate plays weird tricks with a closure, evaluating -// it in the web page's context. Passing arguments from the test -// script's context is awkward (c.f. the various appearances of -// 'table' here). -exports.get_rendered_messages = function (table) { - return casper.evaluate( - function (table) { - var tbl = $("#" + table); - return { - headings: $.map(tbl.find(".recipient_row .message-header-contents"), function ( - elem - ) { - var $clone = $(elem).clone(true); - $clone.find(".recipient_row_date").remove(); - - return $clone.text().trim().replace(/\s+/g, " "); - }), - - bodies: $.map(tbl.find(".message_content"), function (elem) { - return elem.innerHTML; - }), - }; - }, - { - table: table, - } - ); -}; - -exports.get_form_field_value = function (selector) { - return casper.evaluate(function (selector) { - return $(selector).val(); - }, selector); -}; - -exports.get_user_id = function (email) { - return casper.evaluate( - function (email) { - return people.get_user_id(email); - }, - { - email: email, - } - ); -}; - -exports.get_stream_id = function (stream_name) { - return casper.evaluate( - function (stream_name) { - return stream_data.get_stream_id(stream_name); - }, - { - stream_name: stream_name, - } - ); -}; - -// Inject key presses by running some jQuery code in page context. -// PhantomJS and CasperJS don't provide a clean way to insert key -// presses by code, only strings of printable characters. -exports.keypress = function (code) { - casper.evaluate( - function (code) { - $("body").trigger($.Event("keydown", {which: code})); - }, - { - code: code, - } - ); -}; - -exports.then_send_many = function (msgs) { - msgs.forEach(function (msg) { - exports.then_send_message(msg.stream !== undefined ? "stream" : "private", msg); - }); -}; - -// Wait to receive queued messages. -exports.wait_for_receive = function (step) { - // Wait until the last send or get_events result was more than 1000 ms ago. - casper.waitFor(function () { - return timestamp() - last_send_or_update > 1000; - }, step); -}; - -// Wait until the loading spinner goes away (helpful just after logging in). -exports.wait_for_load = function (step) { - casper.waitWhileVisible("#page_loading_indicator", step); -}; - -// innerText sometimes gives us non-breaking space characters, and occasionally -// a different number of spaces than we expect. -exports.normalize_spaces = function (str) { - return str.replace(/\s+/g, " "); -}; - -exports.ltrim = function (str) { - return str.replace(/^\s+/g, ""); -}; - -exports.rtrim = function (str) { - return str.replace(/\s+$/g, ""); -}; - -exports.trim = function (str) { - return exports.rtrim(exports.ltrim(str)); -}; - -// Call get_rendered_messages and then check that the last few headings and -// bodies match the specified arrays. -exports.expected_messages = function (table, headings, bodies) { - casper.test.assertVisible("#" + table, table + " is visible"); - - var msg = exports.get_rendered_messages(table); - - casper.test.assertEquals( - msg.headings.slice(-headings.length), - headings.map(exports.trim), - "Got expected message headings" - ); - - casper.test.assertEquals( - msg.bodies.slice(-bodies.length), - bodies, - "Got expected message bodies" - ); -}; - -exports.un_narrow = function () { - casper.test.info("Un-narrowing"); - if (casper.visible(".message_comp")) { - // close the compose box - common.keypress(27); // Esc - } - common.keypress(27); // Esc -}; - -exports.manage_organization = function () { - casper.then(function () { - var menu_selector = "#settings-dropdown"; - casper.waitUntilVisible(menu_selector, function () { - casper.click(menu_selector); - }); - }); - - casper.then(function () { - casper.test.info("Organization page"); - casper.click('a[href^="#organization"]'); - }); - - casper.waitForSelector("#settings_overlay_container.show", function () { - casper.test.info("Organization page is active"); - casper.test.assertUrlMatch( - /^http:\/\/[^/]+\/#organization/, - "URL suggests we are on organization page" - ); - }); - - casper.then(function () { - casper.click("li[data-section='organization-settings']"); - }); -}; diff --git a/frontend_tests/casper_lib/polyfill.js b/frontend_tests/casper_lib/polyfill.js deleted file mode 100644 index 35de4557bb..0000000000 --- a/frontend_tests/casper_lib/polyfill.js +++ /dev/null @@ -1,14 +0,0 @@ -"use strict"; - -/* eslint-env browser */ - -// PhantomJS doesn’t support new DOMParser().parseFromString(…, "text/html"). -var real_parseFromString = DOMParser.prototype.parseFromString; -DOMParser.prototype.parseFromString = function (string, type) { - if (type === "text/html") { - var doc = document.implementation.createHTMLDocument(""); - doc.documentElement.innerHTML = string; - return doc; - } - return real_parseFromString.apply(this, arguments); -}; diff --git a/frontend_tests/puppeteer_lib/common.js b/frontend_tests/puppeteer_lib/common.js index 7ed2f5c351..8193c22519 100644 --- a/frontend_tests/puppeteer_lib/common.js +++ b/frontend_tests/puppeteer_lib/common.js @@ -5,7 +5,7 @@ const path = require("path"); const puppeteer = require("puppeteer"); -const test_credentials = require("../../var/casper/test_credentials.js").test_credentials; +const test_credentials = require("../../var/puppeteer/test_credentials.js").test_credentials; class CommonUtils { constructor() { @@ -238,7 +238,7 @@ class CommonUtils { actually acks the message, the message will have a temporary id and will not have all the normal message controls. - For the Casper tests, we want to avoid all + For the Puppeteer tests, we want to avoid all the edge cases with locally echoed messages. In order to make sure a message is processed, we use internals to determine the following: diff --git a/frontend_tests/puppeteer_tests/01-login.js b/frontend_tests/puppeteer_tests/01-login.js index 9c76b4094f..18c2967fcc 100644 --- a/frontend_tests/puppeteer_tests/01-login.js +++ b/frontend_tests/puppeteer_tests/01-login.js @@ -1,6 +1,6 @@ "use strict"; -const test_credentials = require("../../var/casper/test_credentials.js").test_credentials; +const test_credentials = require("../../var/puppeteer/test_credentials.js").test_credentials; const common = require("../puppeteer_lib/common"); async function login_tests(page) { diff --git a/frontend_tests/puppeteer_tests/16-settings.js b/frontend_tests/puppeteer_tests/16-settings.js index d750be1128..8388d732f8 100644 --- a/frontend_tests/puppeteer_tests/16-settings.js +++ b/frontend_tests/puppeteer_tests/16-settings.js @@ -2,7 +2,7 @@ const assert = require("assert").strict; -const test_credentials = require("../../var/casper/test_credentials.js").test_credentials; +const test_credentials = require("../../var/puppeteer/test_credentials.js").test_credentials; const common = require("../puppeteer_lib/common"); const OUTGOING_WEBHOOK_BOT_TYPE = "3"; diff --git a/frontend_tests/run-casper b/frontend_tests/run-casper deleted file mode 100755 index 0261bdf8c4..0000000000 --- a/frontend_tests/run-casper +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/env python3 -import argparse -import glob -import os -import shlex -import subprocess -import sys - -# -# In order to use remote casperjs debugging, pass the --remote-debug flag -# This will start a remote debugging session listening on port 7777 -# -# See https://zulip.readthedocs.io/en/latest/testing/testing-with-casper.html -# for more information on how to use remote debugging -# - -ZULIP_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - -os.environ["CASPER_TESTS"] = "1" -os.environ["PHANTOMJS_EXECUTABLE"] = os.path.join(ZULIP_PATH, "node_modules/.bin/phantomjs") -os.environ.pop("http_proxy", "") -os.environ.pop("https_proxy", "") - -usage = """ - - test-js-with-casper # Run all test files - test-js-with-casper 09-navigation.js # Run a single test file - test-js-with-casper 09 # Run a single test file 09-navigation.js - test-js-with-casper 01-login.js 03-narrow.js # Run a few test files - test-js-with-casper 01 03 # Run a few test files, 01-login.js and 03-narrow.js here - - Using loops: - - test-js-with-capser --loop 5 07 # run 5 loops of test 07 ---- -""" -parser = argparse.ArgumentParser(usage=usage) - -parser.add_argument('--skip-flaky-tests', dest='skip_flaky', - action="store_true", - default=False, help='Skip flaky tests') -parser.add_argument('--loop', dest='loop', nargs=1, - action="store", type=int, - default=None, help='Run tests in a loop.') -parser.add_argument('--force', dest='force', - action="store_true", - default=False, help='Run tests despite possible problems.') -parser.add_argument('--verbose', - help='Whether or not to enable verbose mode', - action="store_true", - default=False) -parser.add_argument('--remote-debug', - help='Whether or not to enable remote debugging on port 7777', - action="store_true", - default=False) -parser.add_argument('--xunit-export', dest='xunit_export', - action="store_true", - default=False, help='Export the results of the test suite to an XUnit XML file,') -parser.add_argument('tests', nargs=argparse.REMAINDER, - help='Specific tests to run; by default, runs all tests') -options = parser.parse_args() - -sys.path.insert(0, ZULIP_PATH) - -# check for the venv -from tools.lib import sanity_check - -sanity_check.check_venv(__file__) - -from typing import Iterable, List - -from tools.lib.test_script import assert_provisioning_status_ok, find_js_test_files -from tools.lib.test_server import test_server_running - -assert_provisioning_status_ok(options.force) - -os.chdir(ZULIP_PATH) - -subprocess.check_call(['node', 'node_modules/phantomjs-prebuilt/install.js']) - -os.makedirs('var/casper', exist_ok=True) - -for f in glob.glob('var/casper/casper-failure*.png'): - os.remove(f) - -def reset_database() -> None: - from zerver.lib.test_helpers import reset_emails_in_zulip_realm - reset_emails_in_zulip_realm() - -def run_tests(files: Iterable[str], external_host: str) -> None: - test_dir = os.path.join(ZULIP_PATH, 'frontend_tests/casper_tests') - test_files = find_js_test_files(test_dir, files) - - # 10-admin.js is too flaky! - if options.skip_flaky: - test_files = [fn for fn in test_files if '10-admin' not in fn] - - if options.loop: - loop_cnt = options.loop[0] - print('\n\nWe will use loop mode for these tests:\n') - for test_file in test_files: - print(' ' + os.path.basename(test_file)) - print(f'\nnumber of loops: {loop_cnt}\n') - print() - else: - loop_cnt = None - - remote_debug: List[str] = [] - if options.remote_debug: - remote_debug = ["--remote-debugger-port=7777", "--remote-debugger-autorun=yes"] - - verbose: List[str] = [] - if options.verbose: - verbose = ["--verbose", "--log-level=debug"] - - xunit_export: List[str] = [] - if options.xunit_export: - xunit_export = ["--xunit=var/xunit-test-results/casper/result.xml"] - - def run_tests() -> int: - ret = 1 - for test_file in test_files: - test_name = os.path.basename(test_file) - cmd = ["node_modules/.bin/casperjs"] + remote_debug + verbose + xunit_export + ["test", test_file] - print("\n\n===================== {}\nRunning {}\n\n".format(test_name, " ".join(map(shlex.quote, cmd))), flush=True) - ret = subprocess.call(cmd) - if ret != 0: - return ret - return 0 - - def run_loops(loop_cnt: int) -> None: - while True: - for trial in range(1, loop_cnt + 1): - print(f'\n\n\nSTARTING TRIAL {trial} / {loop_cnt}\n') - ret = run_tests() - if ret == 0: - print(f'`\n\nSUCCESS! trial #{trial}\n\n') - else: - print(f'\n\nFAIL! trial #{trial}\n') - break - - while True: - response = input('Press "q" to quit or enter number of loops: ') - if response == 'q': - return - try: - loop_cnt = int(response) - break - except ValueError: - continue - - with test_server_running(options.force, external_host): - # Important: do next things inside the `with` block, when Django - # will be pointing at the test database. - reset_database() - subprocess.check_call('tools/setup/generate-test-credentials') - - # RUN THE TESTS!!! - if loop_cnt: - run_loops(loop_cnt) - ret = 0 - else: - ret = run_tests() - - if ret != 0: - print(""" -The Casper frontend tests failed! For help debugging, read: - https://zulip.readthedocs.io/en/latest/testing/testing-with-casper.html""", file=sys.stderr) - if os.environ.get("CIRCLECI"): - print("", file=sys.stderr) - print("In CircleCI, the Artifacts tab contains screenshots of the failure.", file=sys.stderr) - print("", file=sys.stderr) - - sys.exit(ret) - -external_host = "zulipdev.com:9981" -run_tests(options.tests, external_host) -sys.exit(0) diff --git a/package.json b/package.json index 944a6519f8..1cec8b8927 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,6 @@ "@typescript-eslint/eslint-plugin": "^3.1.0", "@typescript-eslint/parser": "^3.1.0", "babel-plugin-rewire-ts": "^1.3.3", - "casperjs": "casperjs/casperjs", "difflib": "^0.2.4", "eslint": "^7.2.0", "eslint-config-prettier": "^6.11.0", diff --git a/prettier.config.js b/prettier.config.js index 1966c858a3..f649929ff0 100644 --- a/prettier.config.js +++ b/prettier.config.js @@ -4,12 +4,6 @@ module.exports = { bracketSpacing: false, trailingComma: "all", overrides: [ - { - files: ["frontend_tests/casper_tests/*.js", "frontend_tests/casper_lib/*.js"], - options: { - trailingComma: "es5", - }, - }, { files: ["tsconfig.json"], options: { diff --git a/tools/ci/frontend b/tools/ci/frontend index 76f5c298f6..85b30280c3 100755 --- a/tools/ci/frontend +++ b/tools/ci/frontend @@ -18,18 +18,6 @@ set -x PYTHONWARNINGS=ignore ./tools/check-capitalization --no-generate PYTHONWARNINGS=ignore ./tools/check-frontend-i18n --no-generate -# Disabled because of the frequently flaky -# behaviour of it. -# General pattern of the flaky failure is -# -# FAIL "#zhome" never appeared in 5000ms -# type: uncaughtError -# file: /home/circleci/zulip/frontend_tests/casper_tests/04-compose.js -# error: "#zhome" never appeared in 5000ms -# stack: not provided -# -# ./tools/test-js-with-casper --xunit-export - ./tools/test-js-with-puppeteer # NB: Everything here should be in `tools/test-all`. If there's a diff --git a/tools/run-dev.py b/tools/run-dev.py index 0f92d381b3..2563c67323 100755 --- a/tools/run-dev.py +++ b/tools/run-dev.py @@ -87,7 +87,7 @@ base_port = 9991 if options.test: base_port = 9981 settings_module = "zproject.test_settings" - # Don't auto-reload when running casper tests + # Don't auto-reload when running puppeteer tests runserver_args = ['--noreload'] else: settings_module = "zproject.settings" diff --git a/tools/setup/generate-test-credentials b/tools/setup/generate-test-credentials index a7528f13a2..69068ccefa 100755 --- a/tools/setup/generate-test-credentials +++ b/tools/setup/generate-test-credentials @@ -5,10 +5,10 @@ cd "$(dirname "$0")"/../.. email=desdemona@zulip.com -mkdir -p var/casper +mkdir -p var/puppeteer password=$(./manage.py print_initial_password "$email" | grep -F "$email" | awk '{ print $2 }') -cat > var/casper/test_credentials.js < var/puppeteer/test_credentials.js <