|
| 1 | +import { spawnSync } from "node:child_process"; |
1 | 2 | import { mkdirSync, writeFileSync } from "node:fs";
|
2 | 3 | import path from "node:path";
|
3 | 4 |
|
4 | 5 | import type { BuildOptions } from "@opennextjs/aws/build/helper.js";
|
5 | 6 | import mockFs from "mock-fs";
|
6 |
| -import { afterAll, beforeAll, describe, expect, test, vi } from "vitest"; |
| 7 | +import { afterAll, afterEach, beforeAll, describe, expect, test, vi } from "vitest"; |
7 | 8 |
|
8 | 9 | import { getCacheAssets, populateCache } from "./populate-cache.js";
|
9 | 10 |
|
@@ -83,119 +84,106 @@ vi.mock("node:child_process", () => ({
|
83 | 84 | }));
|
84 | 85 |
|
85 | 86 | describe("populateCache", () => {
|
86 |
| - describe("R2_CACHE_NAME", () => { |
87 |
| - test("calls runWrangler when rcloneBatch is false", async () => { |
88 |
| - const { runWrangler } = await import("../utils/run-wrangler.js"); |
89 |
| - |
90 |
| - const buildOptions: BuildOptions = { |
91 |
| - outputDir: "/test/output", |
92 |
| - } as BuildOptions; |
93 |
| - |
94 |
| - const openNextConfig = { |
95 |
| - default: { |
96 |
| - override: { |
97 |
| - incrementalCache: "cf-r2-incremental-cache", |
98 |
| - }, |
99 |
| - }, |
100 |
| - }; |
101 |
| - |
102 |
| - const wranglerConfig = { |
103 |
| - r2_buckets: [ |
104 |
| - { |
105 |
| - binding: "NEXT_INC_CACHE_R2_BUCKET", |
106 |
| - bucket_name: "test-bucket", |
107 |
| - }, |
108 |
| - ], |
109 |
| - }; |
| 87 | + // Test fixtures |
| 88 | + const createTestBuildOptions = (): BuildOptions => |
| 89 | + ({ |
| 90 | + outputDir: "/test/output", |
| 91 | + }) as BuildOptions; |
| 92 | + |
| 93 | + const createTestOpenNextConfig = () => ({ |
| 94 | + default: { |
| 95 | + override: { |
| 96 | + incrementalCache: "cf-r2-incremental-cache", |
| 97 | + }, |
| 98 | + }, |
| 99 | + }); |
110 | 100 |
|
111 |
| - const populateCacheOptions = { |
112 |
| - target: "local" as const, |
113 |
| - shouldUsePreviewId: false, |
114 |
| - rcloneBatch: false, |
115 |
| - }; |
| 101 | + const createTestWranglerConfig = () => ({ |
| 102 | + r2_buckets: [ |
| 103 | + { |
| 104 | + binding: "NEXT_INC_CACHE_R2_BUCKET", |
| 105 | + bucket_name: "test-bucket", |
| 106 | + }, |
| 107 | + ], |
| 108 | + }); |
116 | 109 |
|
117 |
| - vi.mocked(runWrangler).mockClear(); |
| 110 | + const createTestPopulateCacheOptions = () => ({ |
| 111 | + target: "local" as const, |
| 112 | + shouldUsePreviewId: false, |
| 113 | + }); |
118 | 114 |
|
119 |
| - mockFs({ |
120 |
| - "/test/output": { |
121 |
| - cache: { |
122 |
| - buildID: { |
123 |
| - path: { |
124 |
| - to: { |
125 |
| - "test.cache": JSON.stringify({ data: "test" }), |
126 |
| - }, |
| 115 | + const setupMockFileSystem = () => { |
| 116 | + mockFs({ |
| 117 | + "/test/output": { |
| 118 | + cache: { |
| 119 | + buildID: { |
| 120 | + path: { |
| 121 | + to: { |
| 122 | + "test.cache": JSON.stringify({ data: "test" }), |
127 | 123 | },
|
128 | 124 | },
|
129 | 125 | },
|
130 | 126 | },
|
131 |
| - }); |
132 |
| - |
133 |
| - // For this test we do not need whole configuration, just the part that is being used. |
134 |
| - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
135 |
| - await populateCache(buildOptions, openNextConfig as any, wranglerConfig as any, populateCacheOptions); |
136 |
| - |
137 |
| - expect(runWrangler).toHaveBeenCalled(); |
| 127 | + }, |
| 128 | + }); |
| 129 | + }; |
138 | 130 |
|
| 131 | + describe("R2 incremental cache", () => { |
| 132 | + afterEach(() => { |
139 | 133 | mockFs.restore();
|
| 134 | + vi.unstubAllEnvs(); |
140 | 135 | });
|
141 | 136 |
|
142 |
| - test("calls spawnSync with rclone when rcloneBatch is true", async () => { |
143 |
| - const { spawnSync } = await import("node:child_process"); |
| 137 | + test("uses standard upload when R2 credentials are not provided", async () => { |
| 138 | + const { runWrangler } = await import("../utils/run-wrangler.js"); |
| 139 | + |
| 140 | + // Ensure no batch upload credentials are set |
| 141 | + vi.stubEnv("R2_ACCESS_KEY_ID", undefined); |
| 142 | + vi.stubEnv("R2_SECRET_ACCESS_KEY", undefined); |
| 143 | + vi.stubEnv("R2_ACCOUNT_ID", undefined); |
144 | 144 |
|
145 |
| - const buildOptions: BuildOptions = { |
146 |
| - outputDir: "/test/output", |
147 |
| - } as BuildOptions; |
| 145 | + setupMockFileSystem(); |
| 146 | + vi.mocked(runWrangler).mockClear(); |
148 | 147 |
|
149 |
| - const openNextConfig = { |
150 |
| - default: { |
151 |
| - override: { |
152 |
| - incrementalCache: "cf-r2-incremental-cache", |
153 |
| - }, |
154 |
| - }, |
155 |
| - }; |
| 148 | + // Test uses partial types for simplicity - full config not needed |
| 149 | + await populateCache( |
| 150 | + createTestBuildOptions(), |
| 151 | + createTestOpenNextConfig() as any, // eslint-disable-line @typescript-eslint/no-explicit-any |
| 152 | + createTestWranglerConfig() as any, // eslint-disable-line @typescript-eslint/no-explicit-any |
| 153 | + createTestPopulateCacheOptions() |
| 154 | + ); |
156 | 155 |
|
157 |
| - const wranglerConfig = { |
158 |
| - r2_buckets: [ |
159 |
| - { |
160 |
| - binding: "NEXT_INC_CACHE_R2_BUCKET", |
161 |
| - bucket_name: "test-bucket", |
162 |
| - }, |
163 |
| - ], |
164 |
| - }; |
| 156 | + expect(runWrangler).toHaveBeenCalled(); |
| 157 | + expect(spawnSync).not.toHaveBeenCalled(); |
| 158 | + }); |
165 | 159 |
|
166 |
| - const populateCacheOptions = { |
167 |
| - target: "local" as const, |
168 |
| - shouldUsePreviewId: false, |
169 |
| - rcloneBatch: true, |
170 |
| - }; |
| 160 | + test("uses batch upload with temporary config when R2 credentials are provided", async () => { |
| 161 | + // Set R2 credentials to enable batch upload |
| 162 | + vi.stubEnv("R2_ACCESS_KEY_ID", "test_access_key"); |
| 163 | + vi.stubEnv("R2_SECRET_ACCESS_KEY", "test_secret_key"); |
| 164 | + vi.stubEnv("R2_ACCOUNT_ID", "test_account_id"); |
171 | 165 |
|
| 166 | + setupMockFileSystem(); |
172 | 167 | vi.mocked(spawnSync).mockClear();
|
173 | 168 |
|
174 |
| - mockFs({ |
175 |
| - "/test/output": { |
176 |
| - cache: { |
177 |
| - buildID: { |
178 |
| - path: { |
179 |
| - to: { |
180 |
| - "test.cache": JSON.stringify({ data: "test" }), |
181 |
| - }, |
182 |
| - }, |
183 |
| - }, |
184 |
| - }, |
185 |
| - }, |
186 |
| - }); |
187 |
| - |
188 |
| - // For this test we do not need whole configuration, just the part that is being used. |
189 |
| - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
190 |
| - await populateCache(buildOptions, openNextConfig as any, wranglerConfig as any, populateCacheOptions); |
| 169 | + // Test uses partial types for simplicity - full config not needed |
| 170 | + await populateCache( |
| 171 | + createTestBuildOptions(), |
| 172 | + createTestOpenNextConfig() as any, // eslint-disable-line @typescript-eslint/no-explicit-any |
| 173 | + createTestWranglerConfig() as any, // eslint-disable-line @typescript-eslint/no-explicit-any |
| 174 | + createTestPopulateCacheOptions() |
| 175 | + ); |
191 | 176 |
|
| 177 | + // Verify batch upload was used with correct parameters and temporary config |
192 | 178 | expect(spawnSync).toHaveBeenCalledWith(
|
193 | 179 | "rclone",
|
194 | 180 | expect.arrayContaining(["copy", expect.any(String), "r2:test-bucket"]),
|
195 |
| - expect.any(Object) |
| 181 | + expect.objectContaining({ |
| 182 | + env: expect.objectContaining({ |
| 183 | + RCLONE_CONFIG: expect.stringMatching(/rclone-config-\d+\.conf$/), |
| 184 | + }), |
| 185 | + }) |
196 | 186 | );
|
197 |
| - |
198 |
| - mockFs.restore(); |
199 | 187 | });
|
200 | 188 | });
|
201 | 189 | });
|
0 commit comments