diff --git a/bin/build b/bin/build index 9e7b287fb7d04d95af9ebf9b91e3f011672fb4df..5bc52d532c6b7b2ccbcb836029522cb839bac5e7 100755 --- a/bin/build +++ b/bin/build @@ -18,11 +18,15 @@ version() { } frontend() { + if [ -z ${WEBPACK_OPTS+x} ]; then + WEBPACK_OPTS="-p" + fi + echo "Running 'npm install' to download javascript dependencies..." && npm install && - echo "Running 'webpack -p' to assemble and minify frontend assets..." && - ./node_modules/webpack/bin/webpack.js -p + echo "Running 'webpack $WEBPACK_OPTS' to assemble and minify frontend assets..." && + ./node_modules/.bin/webpack $WEBPACK_OPTS } sample-dataset() { diff --git a/frontend/test/e2e/auth/login.spec.js b/frontend/test/e2e/auth/login.spec.js index 6840d4826da82c1cb5375c695329d1563701aa58..2759f3d07913c9a9ff3d31afff0546c62c6ac3da 100644 --- a/frontend/test/e2e/auth/login.spec.js +++ b/frontend/test/e2e/auth/login.spec.js @@ -1,30 +1,74 @@ -import { startServer, stopServer, isReady } from "../support/start-server"; +import { startServer, isReady } from "../support/start-server"; import webdriver, { By, until } from "selenium-webdriver"; jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000; +async function loginMetabase(driver, username, password) { + await driver.wait(until.elementLocated(By.css("[name=email]"))); + await driver.findElement(By.css("[name=email]")).sendKeys(username); + await driver.findElement(By.css("[name=password]")).sendKeys(password); + await driver.manage().timeouts().implicitlyWait(1000); + await driver.findElement(By.css(".Button.Button--primary")).click(); +} + +function waitForUrl(driver, url, timeout = 5000) { + return driver.wait(async () => await driver.getCurrentUrl() === url, timeout); +} + describe("auth/login", () => { - let host, driver; + let server, driver; beforeAll(async () => { - host = await startServer("metabase"); + server = await startServer("frontend/test/e2e/support/fixtures/setup.db"); driver = new webdriver.Builder() .forBrowser('chrome') .build(); - await driver.navigate().to(`${host}/`); }); - it("should start", async () => { - expect(await isReady(host)).toEqual(true); + it ("should start", async () => { + expect(await isReady(server.host)).toEqual(true); + }); + + describe("has no cookie", () => { + beforeEach(async () => { + await driver.get(`${server.host}/`); + await driver.manage().deleteAllCookies(); + }); + + it ("should take you to the login page", async () => { + await driver.get(`${server.host}/`); + await waitForUrl(driver, `${server.host}/auth/login?redirect=%2F`); + expect(await driver.isElementPresent(By.css("[name=email]"))).toEqual(true); + }); + + it ("should log you in", async () => { + await driver.get(`${server.host}/`); + await loginMetabase(driver, "bob@metabase.com", "12341234"); + await waitForUrl(driver, `${server.host}/`); + }); + + it ("should redirect you after logging in", async () => { + await driver.get(`${server.host}/questions`); + await waitForUrl(driver, `${server.host}/auth/login?redirect=%2Fquestions`); + await loginMetabase(driver, "bob@metabase.com", "12341234"); + await waitForUrl(driver, `${server.host}/questions`); + }); }); - it("should take you to the login page", async () => { - driver.wait(until.elementLocated(By.css("[name=email]"))); - expect(await driver.isElementPresent(By.css("[name=email]"))).toEqual(true); + describe("valid session cookie", () => { + beforeEach(async () => { + await driver.get(`${server.host}/`); + await driver.manage().addCookie("metabase.SESSION_ID", "d65a297d-860b-46b6-a2dd-8f98d37fb2cd"); + }); + + it ("is logged in", async () => { + await driver.get(`${server.host}/`); + await waitForUrl(driver, `${server.host}/`); + }); }); afterAll(async () => { - driver.quit(); - await stopServer("metabase"); + await server.stop(); + await driver.quit(); }); }); diff --git a/frontend/test/e2e/support/fixtures/setup.db.h2.db b/frontend/test/e2e/support/fixtures/setup.db.h2.db new file mode 100644 index 0000000000000000000000000000000000000000..6cda36762c740ce12cbc2047d0fd266b1c99ba19 Binary files /dev/null and b/frontend/test/e2e/support/fixtures/setup.db.h2.db differ diff --git a/frontend/test/e2e/support/start-server.js b/frontend/test/e2e/support/start-server.js index 8a29e2c71d43d75f0edde266773e7d231d11ebc0..ad91bf30984d2c8a36fa5d8777226d4bcd72ce40 100644 --- a/frontend/test/e2e/support/start-server.js +++ b/frontend/test/e2e/support/start-server.js @@ -1,43 +1,82 @@ +import fs from "fs-promise"; +import os from "os"; +import path from "path"; import { spawn } from "child_process"; + import fetch from 'isomorphic-fetch'; import { delay } from '../../../src/metabase/lib/promise'; +let testDbId = 0; +const getDbFile = () => path.join(os.tmpdir(), `metabase-test-${process.pid}-${testDbId++}.db`); + let port = 4000; const getPort = () => port++; const servers = new Map(); -export async function startServer(dbFile) { - if (!servers.has(dbFile)) { - const port = getPort(); - let server = { - dbFile: dbFile, - port: port, - host: `http://localhost:${port}`, - process: spawn("java", ["-jar", "target/uberjar/metabase.jar"], { +class Server { + constructor(dbKey, dbFile) { + this.dbKey = dbKey; + this.dbFile = dbFile; + + this.port = getPort(); + this.host = `http://localhost:${this.port}`; + } + + async start() { + if (!this.process) { + if (this.dbKey !== this.dbFile) { + await fs.copy(`${this.dbKey}.h2.db`, `${this.dbFile}.h2.db`); + } + this.count = 0; + this.process = spawn("java", ["-jar", "target/uberjar/metabase.jar"], { env: { - MB_DB_FILE: dbFile, - MB_JETTY_PORT: port + MB_DB_FILE: this.dbFile, + MB_JETTY_PORT: this.port }, - }), - count: 0 + }) + this.process.on("close", () => { + this.kill(); + }) + } + this.count++; + return this.wait(); + } + + async stop() { + if (--this.count === 0) { + await this.kill(); + } + } + + async wait() { + while (!(await isReady(this.host))) { + await delay(500); + } + } + + async kill() { + if (servers.has(this.dbKey)) { + servers.delete(this.dbKey); + this.process.kill('SIGKILL'); + await fs.unlink(`${this.dbFile}.h2.db`); } - server.process.on("close", () => { - killServer(server); - }) - servers.set(dbFile, server); } - const server = servers.get(dbFile); - server.count++; - await wait(server); - return server.host; } -export async function stopServer(dbFile) { - const server = servers.get(dbFile); - if (--server.count === 0) { - killServer(server); +export async function startServer(dbKey) { + let dbFile = getDbFile(); + if (!dbKey) { + dbKey = dbFile; } + + if (!servers.has(dbKey)) { + servers.set(dbKey, new Server(dbKey, dbFile)); + } + let server = servers.get(dbKey); + + await server.start(); + return server; } export async function isReady(host) { @@ -51,20 +90,8 @@ export async function isReady(host) { return false; } -async function wait(server) { - while (!(await isReady(server.host))) { - await delay(500); - } -} - -function killServer(server) { - console.log("shutting down " + server.dbFile); - servers.delete(server.dbFile); - server.process.kill(); -} - process.once("exit", () => { for (const server of servers) { - killServer(server); + server.kill(); } }); diff --git a/package.json b/package.json index 6aa5a0c64e9bea786846d3a5b7111e19ea93bbf0..b9ea6ee1607fe4e1e41e1dcac32f5544c89108fa 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "file-loader": "^0.8.5", "flow-bin": "^0.24.2", "flow-status-webpack-plugin": "^0.1.4", + "fs-promise": "^0.5.0", "glob": "^5.0.15", "html-webpack-plugin": "^2.14.0", "istanbul-instrumenter-loader": "^0.2.0",