rwsdk 1.0.0-alpha.2 → 1.0.0-alpha.20-test.20250929144616
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/constants.mjs +1 -2
- package/dist/lib/e2e/browser.d.mts +10 -0
- package/dist/lib/e2e/browser.mjs +123 -0
- package/dist/lib/e2e/dev.d.mts +8 -0
- package/dist/lib/e2e/dev.mjs +242 -0
- package/dist/lib/e2e/environment.d.mts +10 -0
- package/dist/lib/e2e/environment.mjs +210 -0
- package/dist/lib/e2e/index.d.mts +8 -0
- package/dist/lib/e2e/index.mjs +8 -0
- package/dist/lib/e2e/poll.d.mts +8 -0
- package/dist/lib/e2e/poll.mjs +31 -0
- package/dist/lib/e2e/release.d.mts +56 -0
- package/dist/lib/e2e/release.mjs +559 -0
- package/dist/lib/e2e/retry.d.mts +4 -0
- package/dist/lib/e2e/retry.mjs +16 -0
- package/dist/lib/e2e/setup.d.mts +2 -0
- package/dist/lib/e2e/setup.mjs +1 -0
- package/dist/lib/e2e/tarball.d.mts +14 -0
- package/dist/lib/e2e/tarball.mjs +99 -0
- package/dist/lib/e2e/testHarness.d.mts +132 -0
- package/dist/lib/e2e/testHarness.mjs +436 -0
- package/dist/lib/e2e/types.d.mts +32 -0
- package/dist/lib/getShortName.mjs +6 -2
- package/dist/lib/getShortName.test.d.mts +1 -0
- package/dist/lib/getShortName.test.mjs +25 -0
- package/dist/lib/getSrcPaths.js +2 -2
- package/dist/lib/hasPkgScript.d.mts +4 -1
- package/dist/lib/hasPkgScript.mjs +9 -6
- package/dist/lib/hasPkgScript.test.d.mts +1 -0
- package/dist/lib/hasPkgScript.test.mjs +33 -0
- package/dist/lib/jsonUtils.mjs +3 -0
- package/dist/lib/jsonUtils.test.d.mts +1 -0
- package/dist/lib/jsonUtils.test.mjs +90 -0
- package/dist/lib/normalizeModulePath.d.mts +5 -0
- package/dist/lib/normalizeModulePath.mjs +1 -1
- package/dist/lib/normalizeModulePath.test.d.mts +1 -0
- package/dist/lib/{normalizeModulePath.test.js → normalizeModulePath.test.mjs} +21 -2
- package/dist/lib/setupEnvFiles.mjs +2 -2
- package/dist/lib/smokeTests/artifacts.mjs +2 -2
- package/dist/lib/smokeTests/browser.d.mts +1 -1
- package/dist/lib/smokeTests/browser.mjs +8 -100
- package/dist/lib/smokeTests/cleanup.mjs +6 -9
- package/dist/lib/smokeTests/codeUpdates.mjs +5 -5
- package/dist/lib/smokeTests/development.mjs +3 -224
- package/dist/lib/smokeTests/environment.d.mts +3 -11
- package/dist/lib/smokeTests/environment.mjs +17 -151
- package/dist/lib/smokeTests/release.d.mts +2 -49
- package/dist/lib/smokeTests/release.mjs +4 -504
- package/dist/lib/smokeTests/reporting.mjs +2 -2
- package/dist/lib/smokeTests/runSmokeTests.mjs +4 -4
- package/dist/lib/smokeTests/utils.mjs +3 -3
- package/dist/lib/testUtils/stubEnvVars.mjs +1 -1
- package/dist/llms/rules/middleware.d.ts +1 -1
- package/dist/llms/rules/middleware.js +4 -4
- package/dist/runtime/client/client.d.ts +2 -2
- package/dist/runtime/client/client.js +2 -2
- package/dist/runtime/client/navigation.test.js +1 -1
- package/dist/runtime/client/types.d.ts +1 -1
- package/dist/runtime/entries/client.d.ts +2 -2
- package/dist/runtime/entries/client.js +2 -2
- package/dist/runtime/entries/router.d.ts +1 -1
- package/dist/runtime/entries/router.js +1 -1
- package/dist/runtime/entries/worker.d.ts +5 -6
- package/dist/runtime/entries/worker.js +5 -6
- package/dist/runtime/imports/worker.js +1 -1
- package/dist/runtime/lib/auth/session.d.ts +2 -2
- package/dist/runtime/lib/auth/session.js +5 -5
- package/dist/runtime/lib/db/DOWorkerDialect.d.ts +1 -1
- package/dist/runtime/lib/db/DOWorkerDialect.js +1 -1
- package/dist/runtime/lib/db/SqliteDurableObject.js +2 -2
- package/dist/runtime/lib/db/index.d.ts +2 -2
- package/dist/runtime/lib/db/index.js +2 -2
- package/dist/runtime/lib/db/migrations.d.ts +1 -1
- package/dist/runtime/lib/db/typeInference/builders/alterTable.d.ts +3 -3
- package/dist/runtime/lib/db/typeInference/builders/columnDefinition.d.ts +1 -1
- package/dist/runtime/lib/db/typeInference/builders/createTable.d.ts +2 -2
- package/dist/runtime/lib/db/typeInference/builders/createView.d.ts +1 -1
- package/dist/runtime/lib/db/typeInference/builders/dropTable.d.ts +1 -1
- package/dist/runtime/lib/db/typeInference/builders/dropView.d.ts +1 -1
- package/dist/runtime/lib/db/typeInference/builders/schema.d.ts +3 -3
- package/dist/runtime/lib/db/typeInference/database.d.ts +2 -2
- package/dist/runtime/lib/memoizeOnId.test.d.ts +1 -0
- package/dist/runtime/lib/memoizeOnId.test.js +49 -0
- package/dist/runtime/lib/realtime/client.js +2 -2
- package/dist/runtime/lib/realtime/durableObject.js +1 -1
- package/dist/runtime/lib/realtime/protocol.test.d.ts +1 -0
- package/dist/runtime/lib/realtime/protocol.test.js +107 -0
- package/dist/runtime/lib/realtime/shared.test.d.ts +1 -0
- package/dist/runtime/lib/realtime/shared.test.js +18 -0
- package/dist/runtime/lib/realtime/validateUpgradeRequest.test.d.ts +1 -0
- package/dist/runtime/lib/realtime/validateUpgradeRequest.test.js +66 -0
- package/dist/runtime/lib/realtime/worker.d.ts +1 -1
- package/dist/runtime/lib/realtime/worker.js +2 -2
- package/dist/runtime/lib/router.d.ts +1 -1
- package/dist/runtime/lib/router.js +40 -22
- package/dist/runtime/lib/router.test.js +591 -3
- package/dist/runtime/lib/rwContext.d.ts +22 -0
- package/dist/runtime/lib/rwContext.js +1 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.d.ts +18 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.js +143 -0
- package/dist/runtime/lib/turnstile/useTurnstile.js +1 -1
- package/dist/runtime/lib/turnstile/verifyTurnstileToken.d.ts +2 -1
- package/dist/runtime/lib/turnstile/verifyTurnstileToken.js +6 -6
- package/dist/runtime/lib/turnstile/verifyTurnstileToken.test.d.ts +1 -0
- package/dist/runtime/lib/turnstile/verifyTurnstileToken.test.js +49 -0
- package/dist/runtime/register/worker.d.ts +1 -1
- package/dist/runtime/register/worker.js +34 -22
- package/dist/runtime/render/assembleDocument.d.ts +6 -0
- package/dist/runtime/render/assembleDocument.js +22 -0
- package/dist/runtime/render/createThenableFromReadableStream.d.ts +1 -0
- package/dist/runtime/render/createThenableFromReadableStream.js +9 -0
- package/dist/runtime/render/normalizeActionResult.d.ts +1 -0
- package/dist/runtime/render/normalizeActionResult.js +43 -0
- package/dist/runtime/render/preloads.d.ts +3 -3
- package/dist/runtime/render/preloads.js +2 -3
- package/dist/runtime/render/{renderRscThenableToHtmlStream.d.ts → renderDocumentHtmlStream.d.ts} +3 -3
- package/dist/runtime/render/renderDocumentHtmlStream.js +39 -0
- package/dist/runtime/render/renderHtmlStream.d.ts +7 -0
- package/dist/runtime/render/renderHtmlStream.js +31 -0
- package/dist/runtime/render/renderToRscStream.d.ts +5 -3
- package/dist/runtime/render/renderToRscStream.js +12 -41
- package/dist/runtime/render/renderToStream.d.ts +3 -2
- package/dist/runtime/render/renderToStream.js +17 -10
- package/dist/runtime/render/stylesheets.d.ts +2 -2
- package/dist/runtime/render/stylesheets.js +2 -3
- package/dist/runtime/requestInfo/types.d.ts +0 -2
- package/dist/runtime/requestInfo/worker.d.ts +1 -1
- package/dist/runtime/requestInfo/worker.js +1 -9
- package/dist/runtime/script.js +1 -1
- package/dist/runtime/ssrBridge.d.ts +3 -2
- package/dist/runtime/ssrBridge.js +3 -2
- package/dist/runtime/worker.d.ts +2 -1
- package/dist/runtime/worker.js +13 -16
- package/dist/scripts/addon.d.mts +1 -0
- package/dist/scripts/addon.mjs +75 -0
- package/dist/scripts/debug-sync.mjs +106 -137
- package/dist/scripts/ensure-deploy-env.mjs +6 -6
- package/dist/scripts/migrate-new.mjs +3 -4
- package/dist/scripts/smoke-test.mjs +2 -2
- package/dist/scripts/worker-run.mjs +7 -9
- package/dist/vite/buildApp.d.mts +2 -1
- package/dist/vite/buildApp.mjs +10 -6
- package/dist/vite/checkIsUsingPrisma.d.mts +4 -0
- package/dist/vite/checkIsUsingPrisma.mjs +2 -2
- package/dist/vite/checkIsUsingPrisma.test.d.mts +1 -0
- package/dist/vite/checkIsUsingPrisma.test.mjs +30 -0
- package/dist/vite/configPlugin.mjs +55 -15
- package/dist/vite/createDirectiveLookupPlugin.d.mts +9 -0
- package/dist/vite/createDirectiveLookupPlugin.mjs +34 -30
- package/dist/vite/createDirectiveLookupPlugin.test.d.mts +1 -0
- package/dist/vite/createDirectiveLookupPlugin.test.mjs +40 -0
- package/dist/vite/createViteAwareResolver.d.mts +1 -2
- package/dist/vite/createViteAwareResolver.mjs +1 -1
- package/dist/vite/directiveModulesDevPlugin.d.mts +4 -1
- package/dist/vite/directiveModulesDevPlugin.mjs +9 -8
- package/dist/vite/directiveModulesDevPlugin.test.d.mts +1 -0
- package/dist/vite/directiveModulesDevPlugin.test.mjs +59 -0
- package/dist/vite/directivesPlugin.d.mts +1 -0
- package/dist/vite/directivesPlugin.mjs +4 -4
- package/dist/vite/directivesPlugin.test.d.mts +1 -0
- package/dist/vite/directivesPlugin.test.mjs +24 -0
- package/dist/vite/ensureAliasArray.test.d.mts +1 -0
- package/dist/vite/ensureAliasArray.test.mjs +71 -0
- package/dist/vite/findSpecifiers.mjs +3 -2
- package/dist/vite/findSpecifiers.test.d.mts +1 -0
- package/dist/vite/findSpecifiers.test.mjs +202 -0
- package/dist/vite/findSsrSpecifiers.mjs +1 -1
- package/dist/vite/findSsrSpecifiers.test.d.mts +1 -0
- package/dist/vite/findSsrSpecifiers.test.mjs +99 -0
- package/dist/vite/getViteEsbuild.mjs +1 -1
- package/dist/vite/hasDirective.d.mts +6 -3
- package/dist/vite/hasDirective.mjs +43 -27
- package/dist/vite/hasDirective.test.d.mts +1 -0
- package/dist/vite/hasDirective.test.mjs +107 -0
- package/dist/vite/index.d.mts +1 -1
- package/dist/vite/invalidateCacheIfPrismaClientChanged.mjs +2 -2
- package/dist/vite/isJsFile.test.d.mts +1 -0
- package/dist/vite/isJsFile.test.mjs +38 -0
- package/dist/vite/{reactConditionsResolverPlugin.d.mts → knownDepsResolverPlugin.d.mts} +3 -3
- package/dist/vite/{reactConditionsResolverPlugin.mjs → knownDepsResolverPlugin.mjs} +29 -24
- package/dist/vite/linkerPlugin.d.mts +8 -0
- package/dist/vite/linkerPlugin.mjs +32 -24
- package/dist/vite/linkerPlugin.test.d.mts +1 -0
- package/dist/vite/linkerPlugin.test.mjs +41 -0
- package/dist/vite/miniflareHMRPlugin.d.mts +5 -0
- package/dist/vite/miniflareHMRPlugin.mjs +7 -7
- package/dist/vite/miniflareHMRPlugin.test.d.mts +1 -0
- package/dist/vite/miniflareHMRPlugin.test.mjs +42 -0
- package/dist/vite/prismaPlugin.mjs +1 -1
- package/dist/vite/redwoodPlugin.d.mts +9 -0
- package/dist/vite/redwoodPlugin.mjs +44 -20
- package/dist/vite/redwoodPlugin.test.d.mts +1 -0
- package/dist/vite/redwoodPlugin.test.mjs +34 -0
- package/dist/vite/resolveForcedPaths.d.mts +4 -0
- package/dist/vite/resolveForcedPaths.mjs +9 -0
- package/dist/vite/runDirectivesScan.d.mts +22 -1
- package/dist/vite/runDirectivesScan.mjs +109 -61
- package/dist/vite/runDirectivesScan.test.d.mts +1 -0
- package/dist/vite/runDirectivesScan.test.mjs +73 -0
- package/dist/vite/ssrBridgePlugin.mjs +10 -3
- package/dist/vite/transformClientComponents.mjs +8 -6
- package/dist/vite/transformClientComponents.test.mjs +117 -59
- package/dist/vite/transformJsxScriptTagsPlugin.mjs +1 -1
- package/dist/vite/transformJsxScriptTagsPlugin.test.mjs +2 -2
- package/dist/vite/transformServerFunctions.d.mts +1 -1
- package/dist/vite/transformServerFunctions.mjs +5 -5
- package/dist/vite/transformServerFunctions.test.mjs +3 -3
- package/package.json +61 -47
- package/dist/runtime/imports/resolveSSRValue.d.ts +0 -1
- package/dist/runtime/imports/resolveSSRValue.js +0 -8
- package/dist/runtime/render/renderRscThenableToHtmlStream.js +0 -54
- package/dist/runtime/render/transformRscToHtmlStream.d.ts +0 -8
- package/dist/runtime/render/transformRscToHtmlStream.js +0 -19
- /package/dist/lib/{normalizeModulePath.test.d.ts → e2e/types.mjs} +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type PackageManager = "pnpm" | "npm" | "yarn" | "yarn-classic";
|
|
2
|
+
/**
|
|
3
|
+
* Options for smoke tests
|
|
4
|
+
*/
|
|
5
|
+
export interface SmokeTestOptions {
|
|
6
|
+
projectDir?: string;
|
|
7
|
+
artifactDir?: string;
|
|
8
|
+
headless?: boolean;
|
|
9
|
+
keep?: boolean;
|
|
10
|
+
sync?: boolean;
|
|
11
|
+
bail?: boolean;
|
|
12
|
+
skipDev?: boolean;
|
|
13
|
+
skipRelease?: boolean;
|
|
14
|
+
skipClient?: boolean;
|
|
15
|
+
packageManager?: PackageManager;
|
|
16
|
+
realtime?: boolean;
|
|
17
|
+
skipHmr?: boolean;
|
|
18
|
+
skipStyleTests?: boolean;
|
|
19
|
+
tarballPath?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Resources created during a test run that need to be cleaned up
|
|
23
|
+
*/
|
|
24
|
+
export interface TestResources {
|
|
25
|
+
tempDirCleanup?: () => Promise<void>;
|
|
26
|
+
workerName?: string;
|
|
27
|
+
targetDir?: string;
|
|
28
|
+
originalCwd: string;
|
|
29
|
+
workerCreatedDuringTest: boolean;
|
|
30
|
+
stopDev?: () => Promise<void>;
|
|
31
|
+
resourceUniqueKey: string;
|
|
32
|
+
}
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
import { relative } from "node:path";
|
|
2
|
-
export const getShortName = (file, root) => file
|
|
1
|
+
import path, { relative } from "node:path";
|
|
2
|
+
export const getShortName = (file, root) => file === root
|
|
3
|
+
? ""
|
|
4
|
+
: file.startsWith(root + path.sep)
|
|
5
|
+
? relative(root, file)
|
|
6
|
+
: file;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { getShortName } from "./getShortName.mjs";
|
|
4
|
+
describe("getShortName", () => {
|
|
5
|
+
it("should return the relative path if the file is inside the root", () => {
|
|
6
|
+
const root = path.join("/Users", "test", "project");
|
|
7
|
+
const file = path.join(root, "src", "index.ts");
|
|
8
|
+
expect(getShortName(file, root)).toBe(path.join("src", "index.ts"));
|
|
9
|
+
});
|
|
10
|
+
it("should return the original path if the file is outside the root", () => {
|
|
11
|
+
const root = path.join("/Users", "test", "project");
|
|
12
|
+
const file = path.join("/Users", "test", "another", "project", "src", "index.ts");
|
|
13
|
+
expect(getShortName(file, root)).toBe(file);
|
|
14
|
+
});
|
|
15
|
+
it("should return an empty string if the paths are identical", () => {
|
|
16
|
+
const root = path.join("/Users", "test", "project");
|
|
17
|
+
const file = path.join("/Users", "test", "project");
|
|
18
|
+
expect(getShortName(file, root)).toBe("");
|
|
19
|
+
});
|
|
20
|
+
it("should handle paths that are substrings of each other correctly", () => {
|
|
21
|
+
const root = path.join("/Users", "test", "project");
|
|
22
|
+
const file = path.join("/Users", "test", "project-longer", "src", "index.ts");
|
|
23
|
+
expect(getShortName(file, root)).toBe(file);
|
|
24
|
+
});
|
|
25
|
+
});
|
package/dist/lib/getSrcPaths.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import ts from "typescript";
|
|
2
|
-
import path from "path";
|
|
3
1
|
import { glob } from "glob";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import ts from "typescript";
|
|
4
4
|
/**
|
|
5
5
|
* Gets all source file paths by parsing tsconfig.json using TypeScript's compiler API.
|
|
6
6
|
* Falls back to a glob pattern if tsconfig parsing fails.
|
|
@@ -1 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { readFile as fsReadFile } from "fs/promises";
|
|
2
|
+
export declare let _pkgCache: Record<string, any> | undefined;
|
|
3
|
+
export declare const hasPkgScript: (projectRootDir: string, script: string, readFile?: typeof fsReadFile) => Promise<any>;
|
|
4
|
+
export declare const _resetPkgCache: () => void;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { readFile } from "fs/promises";
|
|
1
|
+
import { readFile as fsReadFile } from "fs/promises";
|
|
2
2
|
import { resolve } from "path";
|
|
3
|
-
let
|
|
4
|
-
export const hasPkgScript = async (projectRootDir, script) => {
|
|
5
|
-
if (!
|
|
6
|
-
|
|
3
|
+
export let _pkgCache;
|
|
4
|
+
export const hasPkgScript = async (projectRootDir, script, readFile = fsReadFile) => {
|
|
5
|
+
if (!_pkgCache) {
|
|
6
|
+
_pkgCache = JSON.parse((await readFile(resolve(projectRootDir, "package.json"))).toString());
|
|
7
7
|
}
|
|
8
|
-
return
|
|
8
|
+
return _pkgCache?.scripts?.[script];
|
|
9
|
+
};
|
|
10
|
+
export const _resetPkgCache = () => {
|
|
11
|
+
_pkgCache = undefined;
|
|
9
12
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
2
|
+
import { _resetPkgCache, hasPkgScript } from "./hasPkgScript.mjs";
|
|
3
|
+
// Manually reset the cache before each test
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
_resetPkgCache();
|
|
6
|
+
});
|
|
7
|
+
describe("hasPkgScript", () => {
|
|
8
|
+
it("should return the script if it exists", async () => {
|
|
9
|
+
const fakeReadFile = async () => JSON.stringify({ scripts: { "dev:init": "command" } });
|
|
10
|
+
const result = await hasPkgScript("/test", "dev:init", fakeReadFile);
|
|
11
|
+
expect(result).toBe("command");
|
|
12
|
+
});
|
|
13
|
+
it("should return undefined if the script does not exist", async () => {
|
|
14
|
+
const fakeReadFile = async () => JSON.stringify({ scripts: { test: "command" } });
|
|
15
|
+
const result = await hasPkgScript("/test", "dev:init", fakeReadFile);
|
|
16
|
+
expect(result).toBeUndefined();
|
|
17
|
+
});
|
|
18
|
+
it("should return undefined if scripts block does not exist", async () => {
|
|
19
|
+
const fakeReadFile = async () => JSON.stringify({});
|
|
20
|
+
const result = await hasPkgScript("/test", "dev:init", fakeReadFile);
|
|
21
|
+
expect(result).toBeUndefined();
|
|
22
|
+
});
|
|
23
|
+
it("should cache the package.json read", async () => {
|
|
24
|
+
let readCount = 0;
|
|
25
|
+
const fakeReadFile = async () => {
|
|
26
|
+
readCount++;
|
|
27
|
+
return JSON.stringify({ scripts: { "dev:init": "command" } });
|
|
28
|
+
};
|
|
29
|
+
await hasPkgScript("/test", "dev:init", fakeReadFile);
|
|
30
|
+
await hasPkgScript("/test", "dev:init", fakeReadFile);
|
|
31
|
+
expect(readCount).toBe(1);
|
|
32
|
+
});
|
|
33
|
+
});
|
package/dist/lib/jsonUtils.mjs
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { extractAllJson, extractLastJson, parseJson } from "./jsonUtils.mjs";
|
|
3
|
+
describe("jsonUtils", () => {
|
|
4
|
+
describe("extractLastJson", () => {
|
|
5
|
+
it("should extract the last JSON object from a string", () => {
|
|
6
|
+
const output = 'some text {"a":1} some other text {"b":2, "c": {"d": 3}} end';
|
|
7
|
+
expect(extractLastJson(output)).toEqual({ b: 2, c: { d: 3 } });
|
|
8
|
+
});
|
|
9
|
+
it("should extract the last JSON array from a string", () => {
|
|
10
|
+
const output = "start [1, 2] middle [3, 4, [5]] end";
|
|
11
|
+
expect(extractLastJson(output)).toEqual([3, 4, [5]]);
|
|
12
|
+
});
|
|
13
|
+
it("should return the object if the string is just JSON", () => {
|
|
14
|
+
const output = '{"a":1}';
|
|
15
|
+
expect(extractLastJson(output)).toEqual({ a: 1 });
|
|
16
|
+
});
|
|
17
|
+
it("should handle nested structures correctly", () => {
|
|
18
|
+
const output = '{"a":{"b":{"c":"d"}}}';
|
|
19
|
+
expect(extractLastJson(output)).toEqual({ a: { b: { c: "d" } } });
|
|
20
|
+
});
|
|
21
|
+
it("should return null if no valid JSON is found", () => {
|
|
22
|
+
const output = "this is just some text without json";
|
|
23
|
+
expect(extractLastJson(output)).toBeNull();
|
|
24
|
+
});
|
|
25
|
+
it("should return null for malformed JSON", () => {
|
|
26
|
+
const output = '{"a":1, "b":}';
|
|
27
|
+
expect(extractLastJson(output)).toBeNull();
|
|
28
|
+
});
|
|
29
|
+
it("should handle undefined and empty string input", () => {
|
|
30
|
+
expect(extractLastJson(undefined)).toBeNull();
|
|
31
|
+
expect(extractLastJson("")).toBeNull();
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
describe("extractAllJson", () => {
|
|
35
|
+
it("should extract all JSON objects from a string", () => {
|
|
36
|
+
const output = '{"a":1} some text {"b":2} and then {"c":3, "d": [4]}';
|
|
37
|
+
expect(extractAllJson(output)).toEqual([
|
|
38
|
+
{ a: 1 },
|
|
39
|
+
{ b: 2 },
|
|
40
|
+
{ c: 3, d: [4] },
|
|
41
|
+
]);
|
|
42
|
+
});
|
|
43
|
+
it("should extract all JSON arrays from a string", () => {
|
|
44
|
+
const output = "[1,2] then [3,4]";
|
|
45
|
+
expect(extractAllJson(output)).toEqual([
|
|
46
|
+
[1, 2],
|
|
47
|
+
[3, 4],
|
|
48
|
+
]);
|
|
49
|
+
});
|
|
50
|
+
it("should handle a mix of objects and arrays", () => {
|
|
51
|
+
const output = '{"a":1} [2,3] {"b":4}';
|
|
52
|
+
expect(extractAllJson(output)).toEqual([{ a: 1 }, [2, 3], { b: 4 }]);
|
|
53
|
+
});
|
|
54
|
+
it("should return an empty array if no JSON is found", () => {
|
|
55
|
+
const output = "no json here";
|
|
56
|
+
expect(extractAllJson(output)).toEqual([]);
|
|
57
|
+
});
|
|
58
|
+
it("should ignore malformed JSON", () => {
|
|
59
|
+
const output = '{"a":1} {"b":2,} [3,4]';
|
|
60
|
+
expect(extractAllJson(output)).toEqual([{ a: 1 }, [3, 4]]);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe("parseJson", () => {
|
|
64
|
+
it("should parse the last JSON object by default", () => {
|
|
65
|
+
const output = '{"a":1} {"b":2}';
|
|
66
|
+
expect(parseJson(output, {})).toEqual({ b: 2 });
|
|
67
|
+
});
|
|
68
|
+
it("should return the default value if no JSON is found", () => {
|
|
69
|
+
const output = "no json";
|
|
70
|
+
expect(parseJson(output, { default: true })).toEqual({ default: true });
|
|
71
|
+
});
|
|
72
|
+
it("should find an object with a uuid property when requested", () => {
|
|
73
|
+
const output = '{"a":1} {"uuid":"123-abc", "data": "yes"} {"c":3}';
|
|
74
|
+
expect(parseJson(output, {}, true)).toEqual({
|
|
75
|
+
uuid: "123-abc",
|
|
76
|
+
data: "yes",
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
it("should return the last object if findUuid is true but no object with uuid is found", () => {
|
|
80
|
+
const output = '{"a":1} {"b":2}';
|
|
81
|
+
expect(parseJson(output, {}, true)).toEqual({ b: 2 });
|
|
82
|
+
});
|
|
83
|
+
it("should return the default value if findUuid is true and no JSON is found", () => {
|
|
84
|
+
const output = "no json";
|
|
85
|
+
expect(parseJson(output, { default: true }, true)).toEqual({
|
|
86
|
+
default: true,
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find the number of common ancestor segments between two absolute paths.
|
|
3
|
+
* Returns the count of shared directory segments from the root.
|
|
4
|
+
*/
|
|
5
|
+
export declare function findCommonAncestorDepth(path1: string, path2: string): number;
|
|
1
6
|
/**
|
|
2
7
|
* Normalize a module path to a consistent form.
|
|
3
8
|
* Returns slash-prefixed paths for files within project root,
|
|
@@ -4,7 +4,7 @@ import { normalizePath as normalizePathSeparators } from "vite";
|
|
|
4
4
|
* Find the number of common ancestor segments between two absolute paths.
|
|
5
5
|
* Returns the count of shared directory segments from the root.
|
|
6
6
|
*/
|
|
7
|
-
function findCommonAncestorDepth(path1, path2) {
|
|
7
|
+
export function findCommonAncestorDepth(path1, path2) {
|
|
8
8
|
const segments1 = path1.split("/").filter(Boolean);
|
|
9
9
|
const segments2 = path2.split("/").filter(Boolean);
|
|
10
10
|
let commonLength = 0;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,5 +1,24 @@
|
|
|
1
|
-
import { describe,
|
|
2
|
-
import { normalizeModulePath } from "./normalizeModulePath.mjs";
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { findCommonAncestorDepth, normalizeModulePath, } from "./normalizeModulePath.mjs";
|
|
3
|
+
describe("findCommonAncestorDepth", () => {
|
|
4
|
+
it("should return the correct depth for common paths", () => {
|
|
5
|
+
expect(findCommonAncestorDepth("/a/b/c", "/a/b/d")).toBe(2);
|
|
6
|
+
});
|
|
7
|
+
it("should return 0 for completely different paths", () => {
|
|
8
|
+
expect(findCommonAncestorDepth("/a/b/c", "/d/e/f")).toBe(0);
|
|
9
|
+
});
|
|
10
|
+
it("should handle identical paths", () => {
|
|
11
|
+
expect(findCommonAncestorDepth("/a/b/c", "/a/b/c")).toBe(3);
|
|
12
|
+
});
|
|
13
|
+
it("should handle paths of different lengths", () => {
|
|
14
|
+
expect(findCommonAncestorDepth("/a/b/c", "/a/b/c/d/e")).toBe(3);
|
|
15
|
+
});
|
|
16
|
+
it("should handle the root path", () => {
|
|
17
|
+
expect(findCommonAncestorDepth("/", "/a/b")).toBe(0);
|
|
18
|
+
expect(findCommonAncestorDepth("/a", "/")).toBe(0);
|
|
19
|
+
expect(findCommonAncestorDepth("/", "/")).toBe(0);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
3
22
|
describe("normalizeModulePath", () => {
|
|
4
23
|
describe("1. Project-local paths", () => {
|
|
5
24
|
it("Relative file", () => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { resolve } from "node:path";
|
|
2
|
-
import { symlink, copyFile } from "node:fs/promises";
|
|
3
1
|
import { pathExists } from "fs-extra";
|
|
2
|
+
import { copyFile, symlink } from "node:fs/promises";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
4
|
export async function setupEnvFiles({ rootDir, }) {
|
|
5
5
|
const envPath = resolve(rootDir, ".env");
|
|
6
6
|
const devVarsPath = resolve(rootDir, ".dev.vars");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { createWriteStream, existsSync, mkdirSync } from "fs";
|
|
2
|
+
import { mkdirp, pathExists } from "fs-extra";
|
|
1
3
|
import * as fs from "fs/promises";
|
|
2
4
|
import { join } from "path";
|
|
3
|
-
import { mkdirp, pathExists } from "fs-extra";
|
|
4
|
-
import { createWriteStream, existsSync, mkdirSync } from "fs";
|
|
5
5
|
import { log } from "./constants.mjs";
|
|
6
6
|
// Stream capturer for logging
|
|
7
7
|
export const capturer = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { Browser, Page } from "puppeteer-core";
|
|
1
2
|
import { SmokeTestOptions, SmokeTestResult } from "./types.mjs";
|
|
2
|
-
import type { Page, Browser } from "puppeteer-core";
|
|
3
3
|
export declare function checkUrlStyles(page: Page, expectedColor: "red" | "green"): Promise<void>;
|
|
4
4
|
export declare function checkClientModuleStyles(page: Page, expectedColor: "blue" | "green"): Promise<void>;
|
|
5
5
|
/**
|
|
@@ -1,19 +1,14 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
2
|
import { join } from "path";
|
|
3
|
-
import { pathExists } from "fs-extra";
|
|
4
|
-
import { log } from "./constants.mjs";
|
|
5
|
-
import { mkdirp } from "fs-extra";
|
|
6
|
-
import { install, resolveBuildId, computeExecutablePath, detectBrowserPlatform, Browser as PuppeteerBrowser, } from "@puppeteer/browsers";
|
|
7
|
-
import puppeteer from "puppeteer-core";
|
|
8
|
-
import { takeScreenshot } from "./artifacts.mjs";
|
|
9
|
-
import { RETRIES } from "./constants.mjs";
|
|
10
3
|
import { $ } from "../$.mjs";
|
|
11
|
-
import {
|
|
4
|
+
import { getBrowserPath as getE2EBrowserPath, launchBrowser as launchE2EBrowser, } from "../../lib/e2e/browser.mjs";
|
|
5
|
+
import { takeScreenshot } from "./artifacts.mjs";
|
|
6
|
+
import { log, RETRIES } from "./constants.mjs";
|
|
12
7
|
import { reportSmokeTestResult } from "./reporting.mjs";
|
|
13
8
|
import { updateTestStatus } from "./state.mjs";
|
|
14
|
-
import * as fs from "fs/promises";
|
|
15
|
-
import { template as urlStylesTemplate } from "./templates/smokeTestUrlStyles.css.template";
|
|
16
9
|
import { template as clientStylesTemplate } from "./templates/smokeTestClientStyles.module.css.template";
|
|
10
|
+
import { template as urlStylesTemplate } from "./templates/smokeTestUrlStyles.css.template";
|
|
11
|
+
import { fail, withRetries } from "./utils.mjs";
|
|
17
12
|
export async function checkUrlStyles(page, expectedColor) {
|
|
18
13
|
const selector = '[data-testid="smoke-test-url-styles"]';
|
|
19
14
|
log(`Checking for element with selector: ${selector}`);
|
|
@@ -86,100 +81,13 @@ export async function checkClientModuleStyles(page, expectedColor) {
|
|
|
86
81
|
* Launch a browser instance
|
|
87
82
|
*/
|
|
88
83
|
export async function launchBrowser(browserPath, headless = true) {
|
|
89
|
-
|
|
90
|
-
if (!browserPath) {
|
|
91
|
-
log("Getting browser executable path");
|
|
92
|
-
browserPath = await getBrowserPath();
|
|
93
|
-
}
|
|
94
|
-
console.log(`🚀 Launching browser from ${browserPath} (headless: ${headless})`);
|
|
95
|
-
log("Starting browser with puppeteer");
|
|
96
|
-
return await puppeteer.launch({
|
|
97
|
-
executablePath: browserPath,
|
|
98
|
-
headless,
|
|
99
|
-
args: ["--no-sandbox", "--disable-setuid-sandbox"],
|
|
100
|
-
});
|
|
84
|
+
return launchE2EBrowser(browserPath, headless);
|
|
101
85
|
}
|
|
102
86
|
/**
|
|
103
87
|
* Get the browser executable path
|
|
104
88
|
*/
|
|
105
89
|
export async function getBrowserPath(testOptions) {
|
|
106
|
-
|
|
107
|
-
// First try using environment variable if set
|
|
108
|
-
if (process.env.CHROME_PATH) {
|
|
109
|
-
console.log(`Using Chrome from environment variable: ${process.env.CHROME_PATH}`);
|
|
110
|
-
return process.env.CHROME_PATH;
|
|
111
|
-
}
|
|
112
|
-
// Detect platform
|
|
113
|
-
log("Detecting platform");
|
|
114
|
-
const platform = detectBrowserPlatform();
|
|
115
|
-
if (!platform) {
|
|
116
|
-
log("ERROR: Failed to detect browser platform");
|
|
117
|
-
throw new Error("Failed to detect browser platform");
|
|
118
|
-
}
|
|
119
|
-
log("Detected platform: %s", platform);
|
|
120
|
-
// Define a consistent cache directory path in system temp folder
|
|
121
|
-
const rwCacheDir = join(os.tmpdir(), "redwoodjs-smoke-test-cache");
|
|
122
|
-
await mkdirp(rwCacheDir);
|
|
123
|
-
log("Using cache directory: %s", rwCacheDir);
|
|
124
|
-
// Determine browser type based on headless option
|
|
125
|
-
const browser = testOptions?.headless === false
|
|
126
|
-
? PuppeteerBrowser.CHROME
|
|
127
|
-
: PuppeteerBrowser.CHROMEHEADLESSSHELL;
|
|
128
|
-
log(`Using browser type: ${browser}`);
|
|
129
|
-
// Resolve the buildId for the stable Chrome version - do this once
|
|
130
|
-
log("Resolving Chrome buildId for stable channel");
|
|
131
|
-
const buildId = await resolveBuildId(browser, platform, "stable");
|
|
132
|
-
log("Resolved buildId: %s", buildId);
|
|
133
|
-
// Create installation options - use them consistently
|
|
134
|
-
const installOptions = {
|
|
135
|
-
browser,
|
|
136
|
-
platform,
|
|
137
|
-
cacheDir: rwCacheDir,
|
|
138
|
-
buildId,
|
|
139
|
-
unpack: true,
|
|
140
|
-
};
|
|
141
|
-
try {
|
|
142
|
-
// Try to compute the path first (this will check if it's installed)
|
|
143
|
-
log("Attempting to find existing Chrome installation");
|
|
144
|
-
const path = computeExecutablePath(installOptions);
|
|
145
|
-
if (await pathExists(path)) {
|
|
146
|
-
console.log(`Found existing Chrome at: ${path}`);
|
|
147
|
-
return path;
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
throw new Error("Chrome not found at: " + path);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
catch (error) {
|
|
154
|
-
// If path computation fails, install Chrome
|
|
155
|
-
console.log("No Chrome installation found. Installing Chrome...");
|
|
156
|
-
// Add better error handling for the install step
|
|
157
|
-
try {
|
|
158
|
-
console.log("Downloading Chrome (this may take a few minutes)...");
|
|
159
|
-
await install(installOptions);
|
|
160
|
-
console.log("✅ Chrome installation completed successfully");
|
|
161
|
-
// Now compute the path for the installed browser
|
|
162
|
-
const path = computeExecutablePath(installOptions);
|
|
163
|
-
console.log(`Installed and using Chrome at: ${path}`);
|
|
164
|
-
return path;
|
|
165
|
-
}
|
|
166
|
-
catch (installError) {
|
|
167
|
-
// Provide more detailed error about the browser download failure
|
|
168
|
-
log("ERROR: Failed to download/install Chrome: %O", installError);
|
|
169
|
-
console.error(`❌ Failed to download/install Chrome browser.`);
|
|
170
|
-
console.error(`This is likely a network issue or the browser download URL is unavailable.`);
|
|
171
|
-
console.error(`Error details: ${installError instanceof Error ? installError.message : String(installError)}`);
|
|
172
|
-
// For debug builds, show the full error stack if available
|
|
173
|
-
if (installError instanceof Error && installError.stack) {
|
|
174
|
-
log("Error stack: %s", installError.stack);
|
|
175
|
-
}
|
|
176
|
-
console.log("\nPossible solutions:");
|
|
177
|
-
console.log("1. Check your internet connection");
|
|
178
|
-
console.log("2. Set CHROME_PATH environment variable to an existing Chrome installation");
|
|
179
|
-
console.log("3. Install Chrome manually and run the tests again");
|
|
180
|
-
throw new Error(`Failed to install Chrome browser: ${installError instanceof Error ? installError.message : String(installError)}`);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
90
|
+
return getE2EBrowserPath(testOptions);
|
|
183
91
|
}
|
|
184
92
|
/**
|
|
185
93
|
* Check a URL by performing smoke tests and realtime upgrade
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { setTimeout } from "node:timers/promises";
|
|
3
|
-
import { pathExists } from "fs-extra";
|
|
4
|
-
import { mkdirp } from "fs-extra";
|
|
1
|
+
import { copy, mkdirp, pathExists } from "fs-extra";
|
|
5
2
|
import * as fs from "fs/promises";
|
|
6
|
-
import { copy } from "fs-extra";
|
|
7
|
-
import { relative } from "path";
|
|
8
3
|
import ignore from "ignore";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { isRunningInCI } from "./utils.mjs";
|
|
4
|
+
import { setTimeout } from "node:timers/promises";
|
|
5
|
+
import { join, relative } from "path";
|
|
12
6
|
import { capturer } from "./artifacts.mjs";
|
|
7
|
+
import { log } from "./constants.mjs";
|
|
8
|
+
import { deleteD1Database, deleteWorker, listD1Databases } from "./release.mjs";
|
|
13
9
|
import { state } from "./state.mjs";
|
|
10
|
+
import { isRunningInCI } from "./utils.mjs";
|
|
14
11
|
/**
|
|
15
12
|
* Cleans up any resources used during testing
|
|
16
13
|
*/
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { join } from "path";
|
|
2
1
|
import * as fs from "fs/promises";
|
|
2
|
+
import { parse as parseJsonc } from "jsonc-parser";
|
|
3
|
+
import MagicString from "magic-string";
|
|
4
|
+
import { join } from "path";
|
|
3
5
|
import { log } from "./constants.mjs";
|
|
4
|
-
import { getSmokeTestFunctionsTemplate } from "./templates/smokeTestFunctions.template";
|
|
5
6
|
import { getSmokeTestTemplate } from "./templates/SmokeTest.template";
|
|
6
7
|
import { getSmokeTestClientTemplate } from "./templates/SmokeTestClient.template";
|
|
7
|
-
import { template as smokeTestUrlStylesCssTemplate } from "./templates/smokeTestUrlStyles.css.template";
|
|
8
8
|
import { template as smokeTestClientStylesCssTemplate } from "./templates/smokeTestClientStyles.module.css.template";
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
9
|
+
import { getSmokeTestFunctionsTemplate } from "./templates/smokeTestFunctions.template";
|
|
10
|
+
import { template as smokeTestUrlStylesCssTemplate } from "./templates/smokeTestUrlStyles.css.template";
|
|
11
11
|
/**
|
|
12
12
|
* Creates the smoke test components in the target project directory
|
|
13
13
|
*/
|