Archived
1
0

feat: github-auth flag (#4926)

* feat: github-auth flag

This will allow injecting credentials into code-server if you already
have them.

* Update Code

Contains the GitHub auth changes.

* Add e2e test for GitHub token
This commit is contained in:
Asher
2022-03-02 14:02:51 -06:00
committed by GitHub
parent 3f3a489f33
commit 0e78a147b6
14 changed files with 127 additions and 16 deletions

View File

@ -13,11 +13,12 @@ export const describe = (
name: string,
includeCredentials: boolean,
codeServerArgs: string[],
codeServerEnv: NodeJS.ProcessEnv,
fn: (codeServer: CodeServer) => void,
) => {
test.describe(name, () => {
// This will spawn on demand so nothing is necessary on before.
const codeServer = new CodeServer(name, codeServerArgs)
const codeServer = new CodeServer(name, codeServerArgs, codeServerEnv)
// Kill code-server after the suite has ended. This may happen even without
// doing it explicitly but it seems prudent to be sure.

View File

@ -2,7 +2,7 @@ import { promises as fs } from "fs"
import * as path from "path"
import { describe, test, expect } from "./baseFixture"
describe("CodeServer", true, [], () => {
describe("CodeServer", true, [], {}, () => {
test("should navigate to home page", async ({ codeServerPage }) => {
// We navigate codeServer before each test
// and we start the test with a storage state

View File

@ -1,3 +1,4 @@
import * as path from "path"
import { describe, test } from "./baseFixture"
function runTestExtensionTests() {
@ -11,10 +12,12 @@ function runTestExtensionTests() {
})
}
describe("Extensions", true, [], () => {
const flags = ["--extensions-dir", path.join(__dirname, "./extensions")]
describe("Extensions", true, flags, {}, () => {
runTestExtensionTests()
})
describe("Extensions with --cert", true, ["--cert"], () => {
describe("Extensions with --cert", true, [...flags, "--cert"], {}, () => {
runTestExtensionTests()
})

38
test/e2e/github.test.ts Normal file
View File

@ -0,0 +1,38 @@
import { test as base } from "@playwright/test"
import { describe, expect, test } from "./baseFixture"
if (process.env.GITHUB_TOKEN) {
describe("GitHub token", true, [], {}, () => {
test("should be logged in to pull requests extension", async ({ codeServerPage }) => {
await codeServerPage.exec("git init")
await codeServerPage.exec("git remote add origin https://github.com/coder/code-server")
await codeServerPage.installExtension("GitHub.vscode-pull-request-github")
await codeServerPage.executeCommandViaMenus("View: Show Github")
await codeServerPage.page.click("text=Sign in")
await codeServerPage.page.click("text=Allow")
// It should ask to select an account, one of which will be the one we
// pre-injected.
expect(await codeServerPage.page.isVisible("text=Select an account")).toBe(false)
})
})
describe("No GitHub token", true, [], { GITHUB_TOKEN: "" }, () => {
test("should not be logged in to pull requests extension", async ({ codeServerPage }) => {
await codeServerPage.exec("git init")
await codeServerPage.exec("git remote add origin https://github.com/coder/code-server")
await codeServerPage.installExtension("GitHub.vscode-pull-request-github")
await codeServerPage.executeCommandViaMenus("View: Show Github")
await codeServerPage.page.click("text=Sign in")
await codeServerPage.page.click("text=Allow")
// Since there is no account it will ask directly for the token (because
// we are on localhost; otherwise it would initiate the oauth flow).
expect(await codeServerPage.page.isVisible("text=GitHub Personal Access Token")).toBe(false)
})
})
} else {
base.describe("GitHub token", () => {
base.skip("skipped because GITHUB_TOKEN is not set", () => {
// Playwright will not show this without a function.
})
})
}

View File

@ -2,7 +2,7 @@ import { describe, test, expect } from "./baseFixture"
// This test is to make sure the globalSetup works as expected
// meaning globalSetup ran and stored the storageState
describe("globalSetup", true, [], () => {
describe("globalSetup", true, [], {}, () => {
test("should keep us logged in using the storageState", async ({ codeServerPage }) => {
// Make sure the editor actually loaded
expect(await codeServerPage.isEditorVisible()).toBe(true)

View File

@ -1,7 +1,7 @@
import { PASSWORD } from "../utils/constants"
import { describe, test, expect } from "./baseFixture"
describe("login", false, [], () => {
describe("login", false, [], {}, () => {
test("should see the login page", async ({ codeServerPage }) => {
// It should send us to the login page
expect(await codeServerPage.page.title()).toBe("code-server login")

View File

@ -1,7 +1,7 @@
// NOTE@jsjoeio commenting out until we can figure out what's wrong
// import { describe, test, expect } from "./baseFixture"
// describe("logout", true, [], () => {
// describe("logout", true, [], {}, () => {
// test("should be able logout", async ({ codeServerPage }) => {
// // Recommended by Playwright for async navigation
// // https://github.com/microsoft/playwright/issues/1987#issuecomment-620182151

View File

@ -3,6 +3,7 @@ import * as cp from "child_process"
import { promises as fs } from "fs"
import * as path from "path"
import { Page } from "playwright"
import util from "util"
import { logError, plural } from "../../../src/common/util"
import { onLine } from "../../../src/node/util"
import { PASSWORD, workspaceDir } from "../../utils/constants"
@ -39,7 +40,11 @@ export class CodeServer {
private closed = false
private _workspaceDir: Promise<string> | undefined
constructor(name: string, private readonly codeServerArgs: string[]) {
constructor(
name: string,
private readonly codeServerArgs: string[],
private readonly codeServerEnv: NodeJS.ProcessEnv,
) {
this.logger = logger.named(name)
}
@ -96,6 +101,8 @@ export class CodeServer {
"node",
[
process.env.CODE_SERVER_TEST_ENTRY || ".",
"--extensions-dir",
path.join(dir, "extensions"),
...this.codeServerArgs,
// Using port zero will spawn on a random port.
"--bind-addr",
@ -107,8 +114,6 @@ export class CodeServer {
path.join(dir, "config.yaml"),
"--user-data-dir",
dir,
"--extensions-dir",
path.join(__dirname, "../extensions"),
// The last argument is the workspace to open.
dir,
],
@ -116,6 +121,7 @@ export class CodeServer {
cwd: path.join(__dirname, "../../.."),
env: {
...process.env,
...this.codeServerEnv,
PASSWORD,
},
},
@ -462,4 +468,24 @@ export class CodeServerPage {
await this.reloadUntilEditorIsReady()
}
}
/**
* Execute a command in t root of the instance's workspace directory.
*/
async exec(command: string): Promise<void> {
await util.promisify(cp.exec)(command, {
cwd: await this.workspaceDir,
})
}
/**
* Install an extension by ID to the instance's temporary extension
* directory.
*/
async installExtension(id: string): Promise<void> {
const dir = path.join(await this.workspaceDir, "extensions")
await util.promisify(cp.exec)(`node . --install-extension ${id} --extensions-dir ${dir}`, {
cwd: path.join(__dirname, "../../.."),
})
}
}

View File

@ -1,6 +1,6 @@
import { describe, test, expect } from "./baseFixture"
describe("Open Help > About", true, [], () => {
describe("Open Help > About", true, [], {}, () => {
test("should see code-server version in about dialog", async ({ codeServerPage }) => {
// Open using the menu.
await codeServerPage.navigateMenus(["Help", "About"])

View File

@ -4,7 +4,7 @@ import util from "util"
import { clean, tmpdir } from "../utils/helpers"
import { describe, expect, test } from "./baseFixture"
describe("Integrated Terminal", true, [], () => {
describe("Integrated Terminal", true, [], {}, () => {
const testName = "integrated-terminal"
test.beforeAll(async () => {
await clean(testName)