这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
298 changes: 167 additions & 131 deletions cli/scripts/e2e/e2e.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import execa from "execa";
import { test } from "uvu";
import * as uvu from "uvu";
import * as assert from "uvu/assert";
import { Monorepo } from "../monorepo";
import path from "path";
Expand All @@ -17,166 +17,202 @@ const basicPipeline = {
outputs: ["dist/**"],
},
},
globalDependencies: ["$GLOBAL_ENV_DEPENDENCY"],
};

// This is injected by github actions
process.env.TURBO_TOKEN = "";

let suites = [];
for (let npmClient of ["yarn", "berry", "pnpm", "npm"] as const) {
const Suite = uvu.suite(`${npmClient}`);
const repo = new Monorepo("basics");
repo.init(npmClient, basicPipeline);
repo.install();
repo.addPackage("a", ["b"]);
repo.addPackage("b");
repo.addPackage("c");
repo.linkPackages();
runSmokeTests(repo, npmClient);
runSmokeTests(Suite, repo, npmClient);
const sub = new Monorepo("in-subdirectory");
sub.init(npmClient, basicPipeline, "js");
sub.install();
sub.addPackage("a", ["b"]);
sub.addPackage("b");
sub.addPackage("c");
sub.linkPackages();
runSmokeTests(sub, npmClient, {
runSmokeTests(Suite, sub, npmClient, {
cwd: path.join(sub.root, sub.subdir),
});
suites.push(Suite);
// test that turbo can run from a subdirectory
}

test.run();
for (let s of suites) {
s.run();
}

function runSmokeTests(
function runSmokeTests<T>(
suite: uvu.Test<T>,
repo: Monorepo,
npmClient: "yarn" | "berry" | "pnpm" | "npm",
options: execa.SyncOptions<string> = {}
) {
test(`${npmClient} runs tests and logs ${
options.cwd ? " from " + options.cwd : ""
} `, async () => {
const results = repo.turbo("run", ["test", "--stream", "-vvv"], options);
const out = results.stdout + results.stderr;
assert.equal(0, results.exitCode);
const lines = out.split("\n");
const chash = lines.find((l) => l.startsWith("c:test"));
assert.ok(!!chash, "No hash for c:test");
const splitMessage = chash.split(" ");
const hash = splitMessage[splitMessage.length - 1];
const logFilePath = path.join(
repo.subdir ? repo.subdir + "/" : "",
"node_modules",
".cache",
"turbo",
hash,
".turbo",
"turbo-test.log"
);
let text = "";
assert.not.throws(() => {
text = repo.readFileSync(logFilePath);
}, `Could not read log file from cache ${logFilePath}`);

assert.ok(text.includes("testing c"), "Contains correct output");

repo.newBranch("my-feature-branch");
repo.commitFiles({
[path.join("packages", "a", "test.js")]: `console.log('testingz a');`,
});

const sinceResults = repo.turbo(
"run",
["test", "--since=main", "--stream", "-vvv"],
options
);
const testCLine = (sinceResults.stdout + sinceResults.stderr).split("\n");

assert.equal(
`• Packages changed since main: a`,
testCLine[0],
"Calculates changed packages (--since)"
);
assert.equal(`• Packages in scope: a`, testCLine[1], "Packages in scope");
assert.equal(
`• Running test in 1 packages`,
testCLine[2],
"Runs only in changed packages"
);
assert.ok(
testCLine[3].startsWith(`a:test: cache miss, executing`),
"Cache miss in changed package"
);

// Check cache hit after another run
const since2Results = repo.turbo(
"run",
["test", "--since=main", "--stream", "-vvv"],
options
);
const testCLine2 = (since2Results.stdout + since2Results.stderr).split(
"\n"
);
assert.equal(
`• Packages changed since main: a`,
testCLine2[0],
"Calculates changed packages (--since) after a second run"
);
assert.equal(
`• Packages in scope: a`,
testCLine2[1],
"Packages in scope after a second run"
);
assert.equal(
`• Running test in 1 packages`,
testCLine2[2],
"Runs only in changed packages after a second run"
);

assert.ok(
testCLine2[3].startsWith(`a:test: cache hit, replaying output`),
"Cache hit in changed package after a second run"
);

// Check that hashes are different and trigger a cascade
repo.commitFiles({
[path.join("packages", "b", "test.js")]: `console.log('testingz b');`,
});

const hashChangeResults = repo.turbo("run", ["test", "--stream"], options);
const hashChangeResultsOut =
hashChangeResults.stdout + hashChangeResults.stderr;
console.log("------------------------------------------------------");
console.log(hashChangeResultsOut);
console.log("------------------------------------------------------");
const testCLine3 = hashChangeResultsOut.split("\n");

assert.equal(
`• Packages in scope: a, b, c`,
testCLine3[0],
"Packages in scope after a third run"
);
assert.equal(
`• Running test in 3 packages`,
testCLine3[1],
"Runs correct number of packages"
);
assert.ok(
testCLine3.findIndex((l) =>
l.startsWith("a:test: cache miss, executing")
) >= 0,
`A was impacted.`
);
assert.ok(
testCLine3.findIndex((l) =>
l.startsWith("b:test: cache miss, executing")
) >= 0,
`B was impacted.`
);
assert.ok(
testCLine3.findIndex((l) =>
l.startsWith("c:test: cache hit, replaying output")
) >= 0,
`C was unchanged`
);
suite.after(() => {
repo.cleanup();
});

suite(
`${npmClient} runs tests and logs ${
options.cwd ? " from " + options.cwd : ""
} `,
async () => {
const results = repo.turbo("run", ["test", "--stream", "-vvv"], options);
assert.equal(0, results.exitCode, "exit code should be 0");
const commandOutput = getCommandOutputAsArray(results);
const hash = getHashFromOutput(commandOutput, "c#test");
assert.ok(!!hash, "No hash for c#test");
const cachedLogFilePath = getCachedLogFilePathForTask(
getCachedDirForHash(repo, hash),
"test"
);
let text = "";
assert.not.throws(() => {
text = repo.readFileSync(cachedLogFilePath);
}, `Could not read cached log file from cache ${cachedLogFilePath}`);
assert.ok(text.includes("testing c"), "Contains correct output");
}
);

suite(
`${npmClient} handles filesystem changes ${
options.cwd ? " from " + options.cwd : ""
} `,
async () => {
repo.newBranch("my-feature-branch");
repo.commitFiles({
[path.join("packages", "a", "test.js")]: `console.log('testingz a');`,
});

const sinceCommandOutput = getCommandOutputAsArray(
repo.turbo("run", ["test", "--since=main", "--stream", "-vvv"], options)
);

assert.equal(
`• Packages changed since main: a`,
sinceCommandOutput[0],
"Calculates changed packages (--since)"
);
assert.equal(
`• Packages in scope: a`,
sinceCommandOutput[1],
"Packages in scope"
);
assert.equal(
`• Running test in 1 packages`,
sinceCommandOutput[2],
"Runs only in changed packages"
);
assert.ok(
sinceCommandOutput[3].startsWith(`a:test: cache miss, executing`),
"Cache miss in changed package"
);

// Check cache hit after another run
const sinceCommandSecondRunOutput = getCommandOutputAsArray(
repo.turbo("run", ["test", "--since=main", "--stream", "-vvv"], options)
);
assert.equal(
`• Packages changed since main: a`,
sinceCommandSecondRunOutput[0],
"Calculates changed packages (--since) after a second run"
);
assert.equal(
`• Packages in scope: a`,
sinceCommandSecondRunOutput[1],
"Packages in scope after a second run"
);
assert.equal(
`• Running test in 1 packages`,
sinceCommandSecondRunOutput[2],
"Runs only in changed packages after a second run"
);

assert.ok(
sinceCommandSecondRunOutput[3].startsWith(
`a:test: cache hit, replaying output`
),
"Cache hit in changed package after a second run"
);

// Check that hashes are different and trigger a cascade
repo.commitFiles({
[path.join("packages", "b", "test.js")]: `console.log('testingz b');`,
});

const commandOnceBHasChangedOutput = getCommandOutputAsArray(
repo.turbo("run", ["test", "--stream"], options)
);

assert.equal(
`• Packages in scope: a, b, c`,
commandOnceBHasChangedOutput[0],
"After running, changing source of b, and running `turbo run test` again, should print `Packages in scope: a, b, c`"
);
assert.equal(
`• Running test in 3 packages`,
commandOnceBHasChangedOutput[1],
"After running, changing source of b, and running `turbo run test` again, should print `Running in 3 packages`"
);
assert.ok(
commandOnceBHasChangedOutput.findIndex((l) =>
l.startsWith("a:test: cache miss, executing")
) >= 0,
"After running, changing source of b, and running `turbo run test` again, should print `a:test: cache miss, executing` since a depends on b and b has changed"
);
assert.ok(
commandOnceBHasChangedOutput.findIndex((l) =>
l.startsWith("b:test: cache miss, executing")
) >= 0,
"After running, changing source of b, and running `turbo run test` again, should print `b:test: cache miss, executing` since b has changed"
);
assert.ok(
commandOnceBHasChangedOutput.findIndex((l) =>
l.startsWith("c:test: cache hit, replaying output")
) >= 0,
"After running, changing source of b, and running `turbo run test` again, should print `c:test: cache hit, replaying output` since c should not be impacted by changes to b"
);
}
);
}

function getCommandOutputAsArray(
results: execa.ExecaSyncReturnValue<string>
): string[] {
return (results.stdout + results.stderr).split("\n");
}

function getHashFromOutput(lines: string[], taskId: string): string {
const normalizedTaskId = taskId.replace("#", ":");
const line = lines.find((l) => l.startsWith(normalizedTaskId));
const splitMessage = line.split(" ");
const hash = splitMessage[splitMessage.length - 1];
return hash;
}

function getCachedDirForHash(repo: Monorepo, hash: string): string {
return path.join(
repo.subdir ? repo.subdir + "/" : "",
"node_modules",
".cache",
"turbo",
hash
);
}

function getCachedLogFilePathForTask(
cacheDir: string,
taskName: string
): string {
return path.join(cacheDir, ".turbo", `turbo-${taskName}.log`);
}
2 changes: 1 addition & 1 deletion cli/scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"parse-package-name": "^0.1.0",
"shelljs": "^0.8.4",
"tempy": "^1.0.0",
"uvu": "^0.5.1",
"uvu": "^0.5.3",
"watchlist": "^0.2.3"
},
"scripts": {
Expand Down
14 changes: 4 additions & 10 deletions cli/scripts/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1567,11 +1567,6 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2"
safe-regex "^1.1.0"

totalist@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/totalist/-/totalist-2.0.0.tgz#db6f1e19c0fa63e71339bbb8fba89653c18c7eec"
integrity sha512-+Y17F0YzxfACxTyjfhnJQEe7afPA0GSpYlFkl2VFMxYP7jshQf9gXV7cH47EfToBumFThfKBvfAcoUn6fdNeRQ==

type-fest@^0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.16.0.tgz#3240b891a78b0deae910dbeb86553e552a148860"
Expand Down Expand Up @@ -1622,16 +1617,15 @@ util-deprecate@~1.0.1:
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=

uvu@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.1.tgz#938b85f96b8a478e585363ad1849933b6c481b28"
integrity sha512-JGxttnOGDFs77FaZ0yMUHIzczzQ5R1IlDeNW6Wymw6gAscwMdAffVOP6TlxLIfReZyK8tahoGwWZaTCJzNFDkg==
uvu@^0.5.3:
version "0.5.3"
resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.3.tgz#3d83c5bc1230f153451877bfc7f4aea2392219ae"
integrity sha512-brFwqA3FXzilmtnIyJ+CxdkInkY/i4ErvP7uV0DnUVxQcQ55reuHphorpF+tZoVHK2MniZ/VJzI7zJQoc9T9Yw==
dependencies:
dequal "^2.0.0"
diff "^5.0.0"
kleur "^4.0.3"
sade "^1.7.3"
totalist "^2.0.0"

watchlist@^0.2.3:
version "0.2.3"
Expand Down