Skip to content

Commit 270cafd

Browse files
Refactor monolithic CLI index_test into specialized files (#2106)
* refactor: split index_test.ts into specialized test files * refactor: decompose monolithic cli/index_test.ts into modular components - Extract shared test utilities into cli/index_test_base.ts - Create dedicated test files for help, init, project, compile, and run commands - Update cli/BUILD to reflect the new modular test structure
1 parent 94db369 commit 270cafd

8 files changed

Lines changed: 1340 additions & 1167 deletions

cli/BUILD

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,29 @@ node_modules(
4242
],
4343
)
4444

45+
ts_library(
46+
name = "index_test_base",
47+
srcs = ["index_test_base.ts"],
48+
deps = [
49+
"//core",
50+
"//protos:ts",
51+
"//testing",
52+
"@npm//@types/fs-extra",
53+
"@npm//@types/js-yaml",
54+
"@npm//@types/node",
55+
"@npm//fs-extra",
56+
"@npm//js-yaml",
57+
],
58+
)
59+
4560
ts_test_suite(
4661
name = "tests",
4762
srcs = [
48-
"index_test.ts",
63+
"index_help_test.ts",
64+
"index_init_test.ts",
65+
"index_project_test.ts",
66+
"index_compile_test.ts",
67+
"index_run_e2e_test.ts",
4968
"util_test.ts"
5069
],
5170
data = [
@@ -56,17 +75,21 @@ ts_test_suite(
5675
"@nodejs//:npm",
5776
],
5877
deps = [
78+
":index_test_base",
5979
"//cli",
80+
"//cli/api",
6081
"//core",
6182
"//protos:ts",
6283
"//testing",
6384
"@npm//@types/chai",
6485
"@npm//@types/fs-extra",
6586
"@npm//@types/js-yaml",
87+
"@npm//@types/long",
6688
"@npm//@types/node",
6789
"@npm//chai",
6890
"@npm//fs-extra",
6991
"@npm//js-yaml",
92+
"@npm//ts-mockito",
7093
],
7194
)
7295

cli/index_compile_test.ts

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
import { expect } from "chai";
2+
import * as fs from "fs-extra";
3+
import { dump as dumpYaml, load as loadYaml } from "js-yaml";
4+
import * as path from "path";
5+
6+
import { execFile } from "child_process";
7+
import { cliEntryPointPath, DEFAULT_DATABASE, DEFAULT_LOCATION } from "df/cli/index_test_base";
8+
import { version } from "df/core/version";
9+
import { dataform } from "df/protos/ts";
10+
import { corePackageTarPath, getProcessResult, nodePath, npmPath, suite, test } from "df/testing";
11+
import { TmpDirFixture } from "df/testing/fixtures";
12+
13+
suite("compile command", ({ afterEach }) => {
14+
const tmpDirFixture = new TmpDirFixture(afterEach);
15+
16+
test(
17+
"compile throws an error when dataformCoreVersion not in workflow_settings.yaml and no " +
18+
"package.json exists",
19+
async () => {
20+
const projectDir = tmpDirFixture.createNewTmpDir();
21+
fs.writeFileSync(
22+
path.join(projectDir, "workflow_settings.yaml"),
23+
dumpYaml(dataform.WorkflowSettings.create({ defaultProject: "dataform" }))
24+
);
25+
26+
expect(
27+
(await getProcessResult(execFile(nodePath, [cliEntryPointPath, "compile", projectDir])))
28+
.stderr
29+
).contains(
30+
"dataformCoreVersion must be specified either in workflow_settings.yaml or via a " +
31+
"package.json"
32+
);
33+
}
34+
);
35+
36+
test("compile error when package.json and no package is installed", async () => {
37+
const projectDir = tmpDirFixture.createNewTmpDir();
38+
fs.writeFileSync(
39+
path.join(projectDir, "package.json"),
40+
`{
41+
"dependencies":{
42+
"@dataform/core": "${version}"
43+
}
44+
}`
45+
);
46+
fs.writeFileSync(
47+
path.join(projectDir, "dataform.json"),
48+
`{
49+
"defaultDatabase": "tada-analytics",
50+
"defaultSchema": "df_integration_test",
51+
"assertionSchema": "df_integration_test_assertions",
52+
"defaultLocation": "${DEFAULT_LOCATION}"
53+
}
54+
`
55+
);
56+
57+
expect(
58+
(await getProcessResult(execFile(nodePath, [cliEntryPointPath, "compile", projectDir])))
59+
.stderr
60+
).contains(
61+
"Could not find a recent installed version of @dataform/core in the project. Check that " +
62+
"either `dataformCoreVersion` is specified in `workflow_settings.yaml`, or " +
63+
"`@dataform/core` is specified in `package.json`. If using `package.json`, then run " +
64+
"`dataform install`."
65+
);
66+
});
67+
68+
["package.json", "package-lock.json", "node_modules"].forEach(npmFile => {
69+
test(`compile throws an error when dataformCoreVersion in workflow_settings.yaml and ${npmFile} is present`, async () => {
70+
const projectDir = tmpDirFixture.createNewTmpDir();
71+
fs.writeFileSync(
72+
path.join(projectDir, "workflow_settings.yaml"),
73+
dumpYaml(
74+
dataform.WorkflowSettings.create({
75+
defaultProject: "dataform",
76+
dataformCoreVersion: "3.0.0"
77+
})
78+
)
79+
);
80+
const resolvedNpmPath = path.join(projectDir, npmFile);
81+
if (npmFile === "node_modules") {
82+
fs.mkdirSync(resolvedNpmPath);
83+
} else {
84+
fs.writeFileSync(resolvedNpmPath, "");
85+
}
86+
87+
expect(
88+
(await getProcessResult(execFile(nodePath, [cliEntryPointPath, "compile", projectDir])))
89+
.stderr
90+
).contains(`${npmFile}' unexpected; remove it and try again`);
91+
});
92+
});
93+
});
94+
95+
suite("disable-assertions flag (compilation)", ({ afterEach, beforeEach }) => {
96+
const tmpDirFixture = new TmpDirFixture(afterEach);
97+
let projectDir: string;
98+
99+
async function setupTestProject(): Promise<void> {
100+
const npmCacheDir = tmpDirFixture.createNewTmpDir();
101+
const packageJsonPath = path.join(projectDir, "package.json");
102+
103+
await getProcessResult(
104+
execFile(nodePath, [cliEntryPointPath, "init", projectDir, DEFAULT_DATABASE, DEFAULT_LOCATION])
105+
);
106+
107+
const workflowSettingsPath = path.join(projectDir, "workflow_settings.yaml");
108+
const workflowSettings = dataform.WorkflowSettings.create(
109+
loadYaml(fs.readFileSync(workflowSettingsPath, "utf8"))
110+
);
111+
delete workflowSettings.dataformCoreVersion;
112+
fs.writeFileSync(workflowSettingsPath, dumpYaml(workflowSettings));
113+
114+
fs.writeFileSync(
115+
packageJsonPath,
116+
`{
117+
"dependencies":{
118+
"@dataform/core": "${version}"
119+
}
120+
}`
121+
);
122+
await getProcessResult(
123+
execFile(npmPath, [
124+
"install",
125+
"--prefix",
126+
projectDir,
127+
"--cache",
128+
npmCacheDir,
129+
corePackageTarPath
130+
])
131+
);
132+
133+
const assertionFilePath = path.join(projectDir, "definitions", "test_assertion.sqlx");
134+
fs.ensureFileSync(assertionFilePath);
135+
fs.writeFileSync(
136+
assertionFilePath,
137+
`
138+
config { type: "assertion" }
139+
SELECT 1 WHERE FALSE
140+
`
141+
);
142+
143+
const tableFilePath = path.join(projectDir, "definitions", "example_table.sqlx");
144+
fs.ensureFileSync(tableFilePath);
145+
fs.writeFileSync(
146+
tableFilePath,
147+
`
148+
config {
149+
type: "table",
150+
assertions: {
151+
uniqueKey: ["id"]
152+
}
153+
}
154+
SELECT 1 as id
155+
`
156+
);
157+
}
158+
159+
async function setUpWorkflowSettings(disableAssertions: boolean): Promise<void> {
160+
const workflowSettingsPath = path.join(projectDir, "workflow_settings.yaml");
161+
const workflowSettings = dataform.WorkflowSettings.create(
162+
loadYaml(fs.readFileSync(workflowSettingsPath, "utf8"))
163+
);
164+
workflowSettings.disableAssertions = disableAssertions;
165+
fs.writeFileSync(workflowSettingsPath, dumpYaml(workflowSettings));
166+
}
167+
168+
beforeEach("setup test project", async () => {
169+
projectDir = tmpDirFixture.createNewTmpDir();
170+
await setupTestProject();
171+
});
172+
173+
const expectedCompileResult = {
174+
assertions: [
175+
{
176+
canonicalTarget: {
177+
database: DEFAULT_DATABASE,
178+
name: "dataform_example_table_assertions_uniqueKey_0",
179+
schema: "dataform_assertions"
180+
},
181+
dependencyTargets: [
182+
{
183+
database: DEFAULT_DATABASE,
184+
name: "example_table",
185+
schema: "dataform"
186+
}
187+
],
188+
disabled: true,
189+
fileName: "definitions/example_table.sqlx",
190+
parentAction: {
191+
database: DEFAULT_DATABASE,
192+
name: "example_table",
193+
schema: "dataform"
194+
},
195+
query:
196+
// tslint:disable-next-line:tsr-detect-sql-literal-injection
197+
`\nSELECT\n *\nFROM (\n SELECT\n id,\n COUNT(1) AS index_row_count\n FROM \`${DEFAULT_DATABASE}.dataform.example_table\`\n GROUP BY id\n ) AS data\nWHERE index_row_count > 1\n`,
198+
target: {
199+
database: DEFAULT_DATABASE,
200+
name: "dataform_example_table_assertions_uniqueKey_0",
201+
schema: "dataform_assertions"
202+
}
203+
},
204+
{
205+
canonicalTarget: {
206+
database: DEFAULT_DATABASE,
207+
name: "test_assertion",
208+
schema: "dataform_assertions"
209+
},
210+
disabled: true,
211+
fileName: "definitions/test_assertion.sqlx",
212+
query: "\n\nSELECT 1 WHERE FALSE\n",
213+
target: {
214+
database: DEFAULT_DATABASE,
215+
name: "test_assertion",
216+
schema: "dataform_assertions"
217+
}
218+
}
219+
],
220+
dataformCoreVersion: version,
221+
graphErrors: {},
222+
jitData: {},
223+
projectConfig: {
224+
assertionSchema: "dataform_assertions",
225+
defaultDatabase: DEFAULT_DATABASE,
226+
defaultLocation: DEFAULT_LOCATION,
227+
defaultSchema: "dataform",
228+
disableAssertions: true,
229+
warehouse: "bigquery"
230+
},
231+
tables: [
232+
{
233+
canonicalTarget: {
234+
database: DEFAULT_DATABASE,
235+
name: "example_table",
236+
schema: "dataform"
237+
},
238+
disabled: false,
239+
enumType: "TABLE",
240+
fileName: "definitions/example_table.sqlx",
241+
hermeticity: "NON_HERMETIC",
242+
query: "\n\nSELECT 1 as id\n",
243+
target: {
244+
database: DEFAULT_DATABASE,
245+
name: "example_table",
246+
schema: "dataform"
247+
},
248+
type: "table"
249+
}
250+
],
251+
targets: [
252+
{
253+
database: DEFAULT_DATABASE,
254+
name: "dataform_example_table_assertions_uniqueKey_0",
255+
schema: "dataform_assertions"
256+
},
257+
{
258+
database: DEFAULT_DATABASE,
259+
name: "example_table",
260+
schema: "dataform"
261+
},
262+
{
263+
database: DEFAULT_DATABASE,
264+
name: "test_assertion",
265+
schema: "dataform_assertions"
266+
}
267+
]
268+
};
269+
270+
test("with --disable-assertions flag", async () => {
271+
await setUpWorkflowSettings(false);
272+
273+
const compileResult = await getProcessResult(
274+
execFile(nodePath, [
275+
cliEntryPointPath,
276+
"compile",
277+
projectDir,
278+
"--json",
279+
"--disable-assertions"
280+
])
281+
);
282+
283+
expect(compileResult.exitCode).equals(0);
284+
expect(JSON.parse(compileResult.stdout)).deep.equals(expectedCompileResult);
285+
});
286+
287+
test("with disableAssertions set in workflow_settings.yaml", async () => {
288+
await setUpWorkflowSettings(true);
289+
290+
const compileResult = await getProcessResult(
291+
execFile(nodePath, [cliEntryPointPath, "compile", projectDir, "--json"])
292+
);
293+
294+
expect(compileResult.exitCode).equals(0);
295+
expect(JSON.parse(compileResult.stdout)).deep.equals(expectedCompileResult);
296+
});
297+
});

0 commit comments

Comments
 (0)