|
| 1 | +import * as cp from "child_process" |
1 | 2 | import { promises as fs } from "fs"
|
| 3 | +import * as os from "os" |
2 | 4 | import * as path from "path"
|
| 5 | +import * as util from "util" |
3 | 6 | import { describe, test, expect } from "./baseFixture"
|
| 7 | +import { CodeServer } from "./models/CodeServer" |
| 8 | + |
| 9 | +describe("code-server", true, [], {}, () => { |
| 10 | + // TODO@asher: Generalize this? Could be nice if we were to ever need |
| 11 | + // multiple migration tests in other suites. |
| 12 | + const instances = new Map<string, CodeServer>() |
| 13 | + test.afterAll(async () => { |
| 14 | + const procs = Array.from(instances.values()) |
| 15 | + instances.clear() |
| 16 | + await Promise.all(procs.map((cs) => cs.close())) |
| 17 | + }) |
| 18 | + |
| 19 | + /** |
| 20 | + * Spawn a specific version of code-server using the install script. |
| 21 | + */ |
| 22 | + const spawn = async (version: string, dir?: string): Promise<CodeServer> => { |
| 23 | + let instance = instances.get(version) |
| 24 | + if (!instance) { |
| 25 | + await util.promisify(cp.exec)(`./install.sh --method standalone --version ${version}`, { |
| 26 | + cwd: path.join(__dirname, "../.."), |
| 27 | + }) |
| 28 | + |
| 29 | + instance = new CodeServer( |
| 30 | + "code-server@" + version, |
| 31 | + ["--auth=none"], |
| 32 | + { VSCODE_DEV: "" }, |
| 33 | + dir, |
| 34 | + `${os.homedir()}/.local/lib/code-server-${version}`, |
| 35 | + ) |
| 36 | + |
| 37 | + instances.set(version, instance) |
| 38 | + } |
| 39 | + |
| 40 | + return instance |
| 41 | + } |
4 | 42 |
|
5 |
| -describe("CodeServer", true, [], {}, () => { |
6 | 43 | test("should navigate to home page", async ({ codeServerPage }) => {
|
7 | 44 | // We navigate codeServer before each test
|
8 | 45 | // and we start the test with a storage state
|
@@ -34,24 +71,51 @@ describe("CodeServer", true, [], {}, () => {
|
34 | 71 | await codeServerPage.openFile(file)
|
35 | 72 | })
|
36 | 73 |
|
37 |
| - test("should not share state with other paths", async ({ codeServerPage }) => { |
| 74 | + test("should migrate state to avoid collisions", async ({ codeServerPage }) => { |
| 75 | + // This can take a very long time in development because of how long pages |
| 76 | + // take to load and we are doing a lot of that here. |
| 77 | + test.slow() |
| 78 | + |
38 | 79 | const dir = await codeServerPage.workspaceDir
|
39 |
| - const file = path.join(dir, "foo") |
40 |
| - await fs.writeFile(file, "bar") |
| 80 | + const files = [ |
| 81 | + path.join(dir, "foo"), |
| 82 | + path.join(dir, "bar"), |
| 83 | + ] |
| 84 | + await Promise.all(files.map((file) => { |
| 85 | + return fs.writeFile(file, path.basename(file)) |
| 86 | + })) |
41 | 87 |
|
42 |
| - await codeServerPage.openFile(file) |
| 88 | + // Open a file in the latest instance. |
| 89 | + await codeServerPage.openFile(files[0]) |
| 90 | + await codeServerPage.stateFlush() |
43 | 91 |
|
44 |
| - // If we reload now VS Code will be unable to save the state changes so wait |
45 |
| - // until those have been written to the database. It flushes every five |
46 |
| - // seconds so we need to wait at least that long. |
47 |
| - await codeServerPage.page.waitForTimeout(5500) |
| 92 | + // Open a file in an older version of code-server. It should not see the |
| 93 | + // file opened in the new instance since the database has a different |
| 94 | + // name. This must be accessed through the proxy so it shares the same |
| 95 | + // domain and can write to the same database. |
| 96 | + const cs = await spawn("4.0.2", dir) |
| 97 | + const address = new URL(await cs.address()) |
| 98 | + await codeServerPage.navigate("/proxy/" + address.port + "/") |
| 99 | + await codeServerPage.openFile(files[1]) |
| 100 | + expect(await codeServerPage.tabIsVisible(files[0])).toBe(false) |
| 101 | + await codeServerPage.stateFlush() |
48 | 102 |
|
49 |
| - // The tab should re-open on refresh. |
50 |
| - await codeServerPage.page.reload() |
51 |
| - await codeServerPage.waitForTab(file) |
| 103 | + // Move back to latest code-server. We should see the file we previously |
| 104 | + // opened with it but not the old code-server file because the new instance |
| 105 | + // already created its own database on this path and will avoid migrating. |
| 106 | + await codeServerPage.navigate() |
| 107 | + await codeServerPage.waitForTab(files[0]) |
| 108 | + expect(await codeServerPage.tabIsVisible(files[1])).toBe(false) |
52 | 109 |
|
53 |
| - // The tab should not re-open on a different path. |
54 |
| - await codeServerPage.setup(true, "/vscode") |
55 |
| - expect(await codeServerPage.tabIsVisible(file)).toBe(false) |
| 110 | + // Open a new path in latest code-server. This one should migrate the |
| 111 | + // database from old code-server but see nothing from the new database |
| 112 | + // created on the root. |
| 113 | + await codeServerPage.navigate("/vscode") |
| 114 | + await codeServerPage.waitForTab(files[1]) |
| 115 | + expect(await codeServerPage.tabIsVisible(files[0])).toBe(false) |
| 116 | + // Should still be open after a reload. |
| 117 | + await codeServerPage.navigate("/vscode") |
| 118 | + await codeServerPage.waitForTab(files[1]) |
| 119 | + expect(await codeServerPage.tabIsVisible(files[0])).toBe(false) |
56 | 120 | })
|
57 | 121 | })
|
0 commit comments