@lightdash/cli 2.228.0 → 2.229.0
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/.tsbuildinfo.build +1 -0
- package/package.json +4 -4
- package/dist/.tsbuildinfo +0 -1
- package/dist/config.test.d.ts +0 -2
- package/dist/config.test.d.ts.map +0 -1
- package/dist/config.test.js +0 -72
- package/dist/dbt/context.test.d.ts +0 -2
- package/dist/dbt/context.test.d.ts.map +0 -1
- package/dist/dbt/context.test.js +0 -152
- package/dist/dbt/manifest.test.d.ts +0 -2
- package/dist/dbt/manifest.test.d.ts.map +0 -1
- package/dist/dbt/manifest.test.js +0 -170
- package/dist/dbt/models.test.d.ts +0 -2
- package/dist/dbt/models.test.d.ts.map +0 -1
- package/dist/dbt/models.test.js +0 -139
- package/dist/dbt/profiles.test.d.ts +0 -2
- package/dist/dbt/profiles.test.d.ts.map +0 -1
- package/dist/dbt/profiles.test.js +0 -50
- package/dist/dbt/targets/athena.test.d.ts +0 -2
- package/dist/dbt/targets/athena.test.d.ts.map +0 -1
- package/dist/dbt/targets/athena.test.js +0 -78
- package/dist/dbt/targets/duckdb.test.d.ts +0 -2
- package/dist/dbt/targets/duckdb.test.d.ts.map +0 -1
- package/dist/dbt/targets/duckdb.test.js +0 -149
- package/dist/dbt/targets/redshift.test.d.ts +0 -2
- package/dist/dbt/targets/redshift.test.d.ts.map +0 -1
- package/dist/dbt/targets/redshift.test.js +0 -198
- package/dist/dbt/templating.test.d.ts +0 -2
- package/dist/dbt/templating.test.d.ts.map +0 -1
- package/dist/dbt/templating.test.js +0 -51
- package/dist/dbt/validation.test.d.ts +0 -2
- package/dist/dbt/validation.test.d.ts.map +0 -1
- package/dist/dbt/validation.test.js +0 -67
- package/dist/handlers/apps/appCodeFiles.test.d.ts +0 -2
- package/dist/handlers/apps/appCodeFiles.test.d.ts.map +0 -1
- package/dist/handlers/apps/appCodeFiles.test.js +0 -391
- package/dist/handlers/apps/appsDownload.test.d.ts +0 -2
- package/dist/handlers/apps/appsDownload.test.d.ts.map +0 -1
- package/dist/handlers/apps/appsDownload.test.js +0 -639
- package/dist/handlers/apps/build.test.d.ts +0 -2
- package/dist/handlers/apps/build.test.d.ts.map +0 -1
- package/dist/handlers/apps/build.test.js +0 -252
- package/dist/handlers/apps/createApp.test.d.ts +0 -2
- package/dist/handlers/apps/createApp.test.d.ts.map +0 -1
- package/dist/handlers/apps/createApp.test.js +0 -340
- package/dist/handlers/apps/pathContainment.test.d.ts +0 -2
- package/dist/handlers/apps/pathContainment.test.d.ts.map +0 -1
- package/dist/handlers/apps/pathContainment.test.js +0 -66
- package/dist/handlers/apps/preview.test.d.ts +0 -2
- package/dist/handlers/apps/preview.test.d.ts.map +0 -1
- package/dist/handlers/apps/preview.test.js +0 -353
- package/dist/handlers/apps/previewProxy.test.d.ts +0 -2
- package/dist/handlers/apps/previewProxy.test.d.ts.map +0 -1
- package/dist/handlers/apps/previewProxy.test.js +0 -178
- package/dist/handlers/apps/scaffolding.test.d.ts +0 -2
- package/dist/handlers/apps/scaffolding.test.d.ts.map +0 -1
- package/dist/handlers/apps/scaffolding.test.js +0 -151
- package/dist/handlers/apps/uploadRetry.test.d.ts +0 -2
- package/dist/handlers/apps/uploadRetry.test.d.ts.map +0 -1
- package/dist/handlers/apps/uploadRetry.test.js +0 -103
- package/dist/handlers/apps/validate.test.d.ts +0 -2
- package/dist/handlers/apps/validate.test.d.ts.map +0 -1
- package/dist/handlers/apps/validate.test.js +0 -526
- package/dist/handlers/compile.test.d.ts +0 -2
- package/dist/handlers/compile.test.d.ts.map +0 -1
- package/dist/handlers/compile.test.js +0 -151
- package/dist/handlers/compileProject.test.d.ts +0 -2
- package/dist/handlers/compileProject.test.d.ts.map +0 -1
- package/dist/handlers/compileProject.test.js +0 -637
- package/dist/handlers/compileWarehouseColumnValidation.test.d.ts +0 -2
- package/dist/handlers/compileWarehouseColumnValidation.test.d.ts.map +0 -1
- package/dist/handlers/compileWarehouseColumnValidation.test.js +0 -493
- package/dist/handlers/connectSnowflake.test.d.ts +0 -2
- package/dist/handlers/connectSnowflake.test.d.ts.map +0 -1
- package/dist/handlers/connectSnowflake.test.js +0 -320
- package/dist/handlers/contentAsCode/fileNames.test.d.ts +0 -2
- package/dist/handlers/contentAsCode/fileNames.test.d.ts.map +0 -1
- package/dist/handlers/contentAsCode/fileNames.test.js +0 -79
- package/dist/handlers/contentAsCode/registry.test.d.ts +0 -2
- package/dist/handlers/contentAsCode/registry.test.d.ts.map +0 -1
- package/dist/handlers/contentAsCode/registry.test.js +0 -18
- package/dist/handlers/contentAsCode/resource.test.d.ts +0 -2
- package/dist/handlers/contentAsCode/resource.test.d.ts.map +0 -1
- package/dist/handlers/contentAsCode/resource.test.js +0 -121
- package/dist/handlers/dbt/getDbtVersion.test.d.ts +0 -2
- package/dist/handlers/dbt/getDbtVersion.test.d.ts.map +0 -1
- package/dist/handlers/dbt/getDbtVersion.test.js +0 -106
- package/dist/handlers/deploy.test.d.ts +0 -2
- package/dist/handlers/deploy.test.d.ts.map +0 -1
- package/dist/handlers/deploy.test.js +0 -244
- package/dist/handlers/download.test.d.ts +0 -2
- package/dist/handlers/download.test.d.ts.map +0 -1
- package/dist/handlers/download.test.js +0 -1739
- package/dist/handlers/exportChartImage.test.d.ts +0 -2
- package/dist/handlers/exportChartImage.test.d.ts.map +0 -1
- package/dist/handlers/exportChartImage.test.js +0 -55
- package/dist/handlers/homepagesAsCode.test.d.ts +0 -2
- package/dist/handlers/homepagesAsCode.test.d.ts.map +0 -1
- package/dist/handlers/homepagesAsCode.test.js +0 -72
- package/dist/handlers/lint.test.d.ts +0 -2
- package/dist/handlers/lint.test.d.ts.map +0 -1
- package/dist/handlers/lint.test.js +0 -221
- package/dist/handlers/login.test.d.ts +0 -2
- package/dist/handlers/login.test.d.ts.map +0 -1
- package/dist/handlers/login.test.js +0 -24
- package/dist/handlers/metadataFile.test.d.ts +0 -2
- package/dist/handlers/metadataFile.test.d.ts.map +0 -1
- package/dist/handlers/metadataFile.test.js +0 -46
- package/dist/handlers/organizationContent/customRoles.test.d.ts +0 -2
- package/dist/handlers/organizationContent/customRoles.test.d.ts.map +0 -1
- package/dist/handlers/organizationContent/customRoles.test.js +0 -179
- package/dist/handlers/organizationContent/groups.test.d.ts +0 -2
- package/dist/handlers/organizationContent/groups.test.d.ts.map +0 -1
- package/dist/handlers/organizationContent/groups.test.js +0 -135
- package/dist/handlers/organizationContent/index.test.d.ts +0 -2
- package/dist/handlers/organizationContent/index.test.d.ts.map +0 -1
- package/dist/handlers/organizationContent/index.test.js +0 -212
- package/dist/handlers/organizationContent/themes.test.d.ts +0 -2
- package/dist/handlers/organizationContent/themes.test.d.ts.map +0 -1
- package/dist/handlers/organizationContent/themes.test.js +0 -180
- package/dist/handlers/organizationContent/users.test.d.ts +0 -2
- package/dist/handlers/organizationContent/users.test.d.ts.map +0 -1
- package/dist/handlers/organizationContent/users.test.js +0 -155
- package/dist/handlers/preAggregateAudit.test.d.ts +0 -2
- package/dist/handlers/preAggregateAudit.test.d.ts.map +0 -1
- package/dist/handlers/preAggregateAudit.test.js +0 -102
- package/dist/handlers/renameHandler.test.d.ts +0 -2
- package/dist/handlers/renameHandler.test.d.ts.map +0 -1
- package/dist/handlers/renameHandler.test.js +0 -189
- package/dist/handlers/resolveProjectFlag.test.d.ts +0 -2
- package/dist/handlers/resolveProjectFlag.test.d.ts.map +0 -1
- package/dist/handlers/resolveProjectFlag.test.js +0 -48
- package/dist/handlers/selectProject.test.d.ts +0 -2
- package/dist/handlers/selectProject.test.d.ts.map +0 -1
- package/dist/handlers/selectProject.test.js +0 -224
- package/dist/handlers/setProject.test.d.ts +0 -2
- package/dist/handlers/setProject.test.d.ts.map +0 -1
- package/dist/handlers/setProject.test.js +0 -63
- package/dist/handlers/slugUpdate.test.d.ts +0 -2
- package/dist/handlers/slugUpdate.test.d.ts.map +0 -1
- package/dist/handlers/slugUpdate.test.js +0 -265
- package/dist/handlers/timestampConversion.test.d.ts +0 -2
- package/dist/handlers/timestampConversion.test.d.ts.map +0 -1
- package/dist/handlers/timestampConversion.test.js +0 -87
- package/dist/handlers/upgradeCheck.test.d.ts +0 -2
- package/dist/handlers/upgradeCheck.test.d.ts.map +0 -1
- package/dist/handlers/upgradeCheck.test.js +0 -227
- package/dist/handlers/validate.test.d.ts +0 -2
- package/dist/handlers/validate.test.d.ts.map +0 -1
- package/dist/handlers/validate.test.js +0 -318
- package/dist/handlers/validateSpaceFilter.test.d.ts +0 -2
- package/dist/handlers/validateSpaceFilter.test.d.ts.map +0 -1
- package/dist/handlers/validateSpaceFilter.test.js +0 -79
- package/dist/handlers/warehouseConnection.test.d.ts +0 -2
- package/dist/handlers/warehouseConnection.test.d.ts.map +0 -1
- package/dist/handlers/warehouseConnection.test.js +0 -75
- package/dist/lightdash-config/lightdash-config.test.d.ts +0 -2
- package/dist/lightdash-config/lightdash-config.test.d.ts.map +0 -1
- package/dist/lightdash-config/lightdash-config.test.js +0 -69
- package/dist/prompts/fuzzySearchPrompt.test.d.ts +0 -2
- package/dist/prompts/fuzzySearchPrompt.test.d.ts.map +0 -1
- package/dist/prompts/fuzzySearchPrompt.test.js +0 -53
- package/dist/refsArgument.test.d.ts +0 -2
- package/dist/refsArgument.test.d.ts.map +0 -1
- package/dist/refsArgument.test.js +0 -42
- package/dist/releaseSafety/index.test.d.ts +0 -2
- package/dist/releaseSafety/index.test.d.ts.map +0 -1
- package/dist/releaseSafety/index.test.js +0 -154
- package/dist/releaseSafety/version.test.d.ts +0 -2
- package/dist/releaseSafety/version.test.d.ts.map +0 -1
- package/dist/releaseSafety/version.test.js +0 -22
- package/dist/skills.test.d.ts +0 -2
- package/dist/skills.test.d.ts.map +0 -1
- package/dist/skills.test.js +0 -112
- package/dist/terminal/contentAsCodeOutput.test.d.ts +0 -2
- package/dist/terminal/contentAsCodeOutput.test.d.ts.map +0 -1
- package/dist/terminal/contentAsCodeOutput.test.js +0 -231
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const tslib_1 = require("tslib");
|
|
4
|
-
const common_1 = require("@lightdash/common");
|
|
5
|
-
const node_fetch_1 = require("node-fetch");
|
|
6
|
-
const analytics_1 = require("../analytics/analytics");
|
|
7
|
-
const connectSnowflake_1 = require("./connectSnowflake");
|
|
8
|
-
vi.mock('../analytics/analytics');
|
|
9
|
-
const options = {
|
|
10
|
-
code: '11111111_random-code',
|
|
11
|
-
url: 'https://lightdash.example.com/setup',
|
|
12
|
-
account: 'acme.eu-west-1',
|
|
13
|
-
user: 'lightdash_user',
|
|
14
|
-
};
|
|
15
|
-
const discovery = {
|
|
16
|
-
user: 'lightdash_user',
|
|
17
|
-
defaults: {
|
|
18
|
-
database: 'analytics',
|
|
19
|
-
warehouse: 'lightdash_wh',
|
|
20
|
-
role: 'lightdash_role',
|
|
21
|
-
schema: 'public',
|
|
22
|
-
},
|
|
23
|
-
inventory: {
|
|
24
|
-
databases: [
|
|
25
|
-
{
|
|
26
|
-
name: 'analytics',
|
|
27
|
-
comment: 'Analytics data',
|
|
28
|
-
kind: 'STANDARD',
|
|
29
|
-
sizeBytes: 1234,
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
warehouses: [
|
|
33
|
-
{
|
|
34
|
-
name: 'lightdash_wh',
|
|
35
|
-
size: 'X-Small',
|
|
36
|
-
state: 'STARTED',
|
|
37
|
-
autoSuspendSeconds: 300,
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
roles: [
|
|
41
|
-
{ name: 'lightdash_role', isDefault: true },
|
|
42
|
-
{ name: 'PUBLIC', isDefault: false },
|
|
43
|
-
],
|
|
44
|
-
schemas: [{ databaseName: 'analytics', name: 'public' }],
|
|
45
|
-
},
|
|
46
|
-
};
|
|
47
|
-
const privateKey = '-----BEGIN PRIVATE KEY-----\ntest-private-key\n-----END PRIVATE KEY-----\n';
|
|
48
|
-
const publicKey = 'dGVzdC1wdWJsaWMta2V5';
|
|
49
|
-
const getSessionDiscovery = vi.fn();
|
|
50
|
-
const getUserPublicKeySlots = vi.fn();
|
|
51
|
-
const setUserPublicKey = vi.fn();
|
|
52
|
-
const unsetUserPublicKey = vi.fn();
|
|
53
|
-
const createProgrammaticAccessToken = vi.fn();
|
|
54
|
-
const openDiagnosticConnection = vi.fn();
|
|
55
|
-
const selectOneDiagnosticConnection = vi.fn();
|
|
56
|
-
const closeDiagnosticConnection = vi.fn();
|
|
57
|
-
const warehouseClientFactory = vi.fn(() => ({
|
|
58
|
-
closeDiagnosticConnection,
|
|
59
|
-
createProgrammaticAccessToken,
|
|
60
|
-
getSessionDiscovery,
|
|
61
|
-
getUserPublicKeySlots,
|
|
62
|
-
openDiagnosticConnection,
|
|
63
|
-
selectOneDiagnosticConnection,
|
|
64
|
-
setUserPublicKey,
|
|
65
|
-
unsetUserPublicKey,
|
|
66
|
-
}));
|
|
67
|
-
const fetchMock = vi.fn();
|
|
68
|
-
const write = vi.fn();
|
|
69
|
-
const sleep = vi.fn(async () => undefined);
|
|
70
|
-
const responseForDeposit = () => new node_fetch_1.Response(JSON.stringify({ status: 'ok' }), {
|
|
71
|
-
status: 200,
|
|
72
|
-
headers: { 'Content-Type': 'application/json' },
|
|
73
|
-
});
|
|
74
|
-
const getDepositRequest = () => JSON.parse(String(vi.mocked(fetchMock).mock.calls[0][1]?.body));
|
|
75
|
-
const getDependencies = () => ({
|
|
76
|
-
warehouseClientFactory,
|
|
77
|
-
generateKeyPair: () => ({ privateKey, publicKey }),
|
|
78
|
-
sleep,
|
|
79
|
-
now: () => new Date('2026-07-14T12:00:00.000Z'),
|
|
80
|
-
fetch: fetchMock,
|
|
81
|
-
write,
|
|
82
|
-
});
|
|
83
|
-
const depositInventory = {
|
|
84
|
-
databases: [
|
|
85
|
-
{ name: 'analytics', comment: 'Analytics data', sizeBytes: 1234 },
|
|
86
|
-
],
|
|
87
|
-
warehouses: [{ name: 'lightdash_wh', size: 'X-Small', state: 'STARTED' }],
|
|
88
|
-
roles: [
|
|
89
|
-
{ name: 'lightdash_role', isDefault: true },
|
|
90
|
-
{ name: 'PUBLIC', isDefault: false },
|
|
91
|
-
],
|
|
92
|
-
schemas: [{ database: 'analytics', name: 'public' }],
|
|
93
|
-
};
|
|
94
|
-
const privateKeyCredentials = (values = {}) => ({
|
|
95
|
-
type: common_1.WarehouseTypes.SNOWFLAKE,
|
|
96
|
-
account: options.account,
|
|
97
|
-
user: discovery.user,
|
|
98
|
-
authenticationType: common_1.SnowflakeAuthenticationType.PRIVATE_KEY,
|
|
99
|
-
role: discovery.defaults.role ?? undefined,
|
|
100
|
-
database: discovery.defaults.database ?? '',
|
|
101
|
-
warehouse: discovery.defaults.warehouse ?? '',
|
|
102
|
-
schema: discovery.defaults.schema ?? '',
|
|
103
|
-
privateKey,
|
|
104
|
-
...values,
|
|
105
|
-
});
|
|
106
|
-
describe('connectSnowflakeHandler', () => {
|
|
107
|
-
beforeEach(() => {
|
|
108
|
-
vi.clearAllMocks();
|
|
109
|
-
vi.mocked(analytics_1.categorizeError).mockReturnValue('warehouse_connection');
|
|
110
|
-
vi.mocked(getSessionDiscovery).mockResolvedValue(discovery);
|
|
111
|
-
vi.mocked(getUserPublicKeySlots).mockResolvedValue({
|
|
112
|
-
RSA_PUBLIC_KEY: null,
|
|
113
|
-
RSA_PUBLIC_KEY_2: null,
|
|
114
|
-
});
|
|
115
|
-
vi.mocked(setUserPublicKey).mockResolvedValue(undefined);
|
|
116
|
-
vi.mocked(unsetUserPublicKey).mockResolvedValue(undefined);
|
|
117
|
-
vi.mocked(createProgrammaticAccessToken).mockResolvedValue({
|
|
118
|
-
tokenName: 'LIGHTDASH_ONBOARDING_1234567890',
|
|
119
|
-
tokenSecret: 'pat-secret',
|
|
120
|
-
});
|
|
121
|
-
vi.mocked(openDiagnosticConnection).mockResolvedValue({
|
|
122
|
-
connection: {},
|
|
123
|
-
});
|
|
124
|
-
vi.mocked(selectOneDiagnosticConnection).mockResolvedValue(undefined);
|
|
125
|
-
vi.mocked(closeDiagnosticConnection).mockResolvedValue(undefined);
|
|
126
|
-
vi.mocked(fetchMock).mockResolvedValue(responseForDeposit());
|
|
127
|
-
});
|
|
128
|
-
it('deposits private-key credentials using session defaults', async () => {
|
|
129
|
-
await expect((0, connectSnowflake_1.connectSnowflakeHandler)(options, getDependencies())).resolves.toBeUndefined();
|
|
130
|
-
expect(warehouseClientFactory).toHaveBeenNthCalledWith(1, {
|
|
131
|
-
type: common_1.WarehouseTypes.SNOWFLAKE,
|
|
132
|
-
account: options.account,
|
|
133
|
-
user: options.user,
|
|
134
|
-
authenticationType: common_1.SnowflakeAuthenticationType.OAUTH_AUTHORIZATION_CODE,
|
|
135
|
-
role: undefined,
|
|
136
|
-
database: '',
|
|
137
|
-
warehouse: '',
|
|
138
|
-
schema: '',
|
|
139
|
-
});
|
|
140
|
-
expect(getSessionDiscovery).toHaveBeenCalledWith(options.user);
|
|
141
|
-
expect(setUserPublicKey).toHaveBeenCalledWith(discovery.user, 'RSA_PUBLIC_KEY', publicKey);
|
|
142
|
-
expect(warehouseClientFactory).toHaveBeenNthCalledWith(2, privateKeyCredentials({
|
|
143
|
-
database: '',
|
|
144
|
-
warehouse: '',
|
|
145
|
-
schema: '',
|
|
146
|
-
role: undefined,
|
|
147
|
-
}));
|
|
148
|
-
const request = {
|
|
149
|
-
code: options.code,
|
|
150
|
-
credentials: privateKeyCredentials(),
|
|
151
|
-
inventory: depositInventory,
|
|
152
|
-
};
|
|
153
|
-
expect(getDepositRequest()).toEqual(request);
|
|
154
|
-
expect(write).toHaveBeenCalledWith('Secured with a key pair');
|
|
155
|
-
expect(write).toHaveBeenCalledWith('Connection values resolved: database (session default), warehouse (session default), schema (session default), role (session default)');
|
|
156
|
-
expect(write).not.toHaveBeenCalledWith(expect.stringContaining(options.code));
|
|
157
|
-
expect(write).not.toHaveBeenCalledWith(expect.stringContaining(privateKey));
|
|
158
|
-
const { LightdashAnalytics } = await Promise.resolve().then(() => tslib_1.__importStar(require('../analytics/analytics')));
|
|
159
|
-
expect(vi.mocked(LightdashAnalytics.track)).toHaveBeenCalledWith({
|
|
160
|
-
event: 'connect_snowflake.started',
|
|
161
|
-
properties: {},
|
|
162
|
-
});
|
|
163
|
-
expect(vi.mocked(LightdashAnalytics.track)).toHaveBeenCalledWith({
|
|
164
|
-
event: 'connect_snowflake.completed',
|
|
165
|
-
properties: { method: 'key_pair' },
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
it('prefers explicit flags over session defaults', async () => {
|
|
169
|
-
const overrideOptions = {
|
|
170
|
-
...options,
|
|
171
|
-
database: 'flag_db',
|
|
172
|
-
warehouse: 'flag_wh',
|
|
173
|
-
role: 'flag_role',
|
|
174
|
-
schema: 'flag_schema',
|
|
175
|
-
};
|
|
176
|
-
await expect((0, connectSnowflake_1.connectSnowflakeHandler)(overrideOptions, getDependencies())).resolves.toBeUndefined();
|
|
177
|
-
const request = {
|
|
178
|
-
code: options.code,
|
|
179
|
-
credentials: privateKeyCredentials({
|
|
180
|
-
database: 'flag_db',
|
|
181
|
-
warehouse: 'flag_wh',
|
|
182
|
-
role: 'flag_role',
|
|
183
|
-
schema: 'flag_schema',
|
|
184
|
-
}),
|
|
185
|
-
inventory: depositInventory,
|
|
186
|
-
};
|
|
187
|
-
expect(getDepositRequest()).toEqual(request);
|
|
188
|
-
expect(write).toHaveBeenCalledWith('Connection values resolved: database (flag), warehouse (flag), schema (flag), role (flag)');
|
|
189
|
-
});
|
|
190
|
-
it('omits missing values and deposits capped inventory names', async () => {
|
|
191
|
-
const inventoryNames = Array.from({ length: 105 }, (_, index) => `item_${index}`);
|
|
192
|
-
vi.mocked(getSessionDiscovery).mockResolvedValue({
|
|
193
|
-
...discovery,
|
|
194
|
-
defaults: {
|
|
195
|
-
database: null,
|
|
196
|
-
warehouse: null,
|
|
197
|
-
role: null,
|
|
198
|
-
schema: null,
|
|
199
|
-
},
|
|
200
|
-
inventory: {
|
|
201
|
-
databases: inventoryNames.map((name) => ({
|
|
202
|
-
name,
|
|
203
|
-
comment: null,
|
|
204
|
-
kind: null,
|
|
205
|
-
sizeBytes: null,
|
|
206
|
-
})),
|
|
207
|
-
warehouses: inventoryNames.map((name) => ({
|
|
208
|
-
name,
|
|
209
|
-
size: null,
|
|
210
|
-
state: null,
|
|
211
|
-
autoSuspendSeconds: null,
|
|
212
|
-
})),
|
|
213
|
-
roles: inventoryNames.map((name) => ({
|
|
214
|
-
name,
|
|
215
|
-
isDefault: false,
|
|
216
|
-
})),
|
|
217
|
-
schemas: inventoryNames.map((name) => ({
|
|
218
|
-
databaseName: 'analytics',
|
|
219
|
-
name,
|
|
220
|
-
})),
|
|
221
|
-
},
|
|
222
|
-
});
|
|
223
|
-
await expect((0, connectSnowflake_1.connectSnowflakeHandler)(options, getDependencies())).resolves.toBeUndefined();
|
|
224
|
-
const request = getDepositRequest();
|
|
225
|
-
expect(request.credentials).not.toHaveProperty('database');
|
|
226
|
-
expect(request.credentials).not.toHaveProperty('warehouse');
|
|
227
|
-
expect(request.credentials).not.toHaveProperty('schema');
|
|
228
|
-
expect(request.credentials).not.toHaveProperty('role');
|
|
229
|
-
expect(request.inventory).toEqual({
|
|
230
|
-
databases: inventoryNames
|
|
231
|
-
.slice(0, 100)
|
|
232
|
-
.map((name) => ({ name, comment: null, sizeBytes: null })),
|
|
233
|
-
warehouses: inventoryNames
|
|
234
|
-
.slice(0, 100)
|
|
235
|
-
.map((name) => ({ name, size: null, state: null })),
|
|
236
|
-
roles: inventoryNames
|
|
237
|
-
.slice(0, 100)
|
|
238
|
-
.map((name) => ({ name, isDefault: false })),
|
|
239
|
-
schemas: inventoryNames
|
|
240
|
-
.slice(0, 1000)
|
|
241
|
-
.map((name) => ({ database: 'analytics', name })),
|
|
242
|
-
});
|
|
243
|
-
expect(write).toHaveBeenCalledWith('Connection values resolved: none');
|
|
244
|
-
expect(write).toHaveBeenCalledWith('Finish choosing database, warehouse, schema, role in the browser.');
|
|
245
|
-
});
|
|
246
|
-
it('selects the first free Snowflake public-key slot', async () => {
|
|
247
|
-
vi.mocked(getUserPublicKeySlots).mockResolvedValue({
|
|
248
|
-
RSA_PUBLIC_KEY: 'SHA256:existing-key',
|
|
249
|
-
RSA_PUBLIC_KEY_2: null,
|
|
250
|
-
});
|
|
251
|
-
await expect((0, connectSnowflake_1.connectSnowflakeHandler)(options, getDependencies())).resolves.toBeUndefined();
|
|
252
|
-
expect(setUserPublicKey).toHaveBeenCalledWith(discovery.user, 'RSA_PUBLIC_KEY_2', publicKey);
|
|
253
|
-
expect(createProgrammaticAccessToken).not.toHaveBeenCalled();
|
|
254
|
-
});
|
|
255
|
-
it('uses a unique PAT name when both key slots are occupied', async () => {
|
|
256
|
-
vi.mocked(getUserPublicKeySlots).mockResolvedValue({
|
|
257
|
-
RSA_PUBLIC_KEY: 'SHA256:existing-key-1',
|
|
258
|
-
RSA_PUBLIC_KEY_2: 'SHA256:existing-key-2',
|
|
259
|
-
});
|
|
260
|
-
await expect((0, connectSnowflake_1.connectSnowflakeHandler)(options, getDependencies())).resolves.toBeUndefined();
|
|
261
|
-
expect(setUserPublicKey).not.toHaveBeenCalled();
|
|
262
|
-
expect(createProgrammaticAccessToken).toHaveBeenCalledWith(expect.stringMatching(/^LIGHTDASH_ONBOARDING_\d+$/), 365, 60);
|
|
263
|
-
const request = {
|
|
264
|
-
code: options.code,
|
|
265
|
-
credentials: {
|
|
266
|
-
type: common_1.WarehouseTypes.SNOWFLAKE,
|
|
267
|
-
account: options.account,
|
|
268
|
-
user: discovery.user,
|
|
269
|
-
authenticationType: common_1.SnowflakeAuthenticationType.PASSWORD,
|
|
270
|
-
role: discovery.defaults.role ?? undefined,
|
|
271
|
-
database: discovery.defaults.database ?? '',
|
|
272
|
-
warehouse: discovery.defaults.warehouse ?? '',
|
|
273
|
-
schema: discovery.defaults.schema ?? '',
|
|
274
|
-
password: 'pat-secret',
|
|
275
|
-
},
|
|
276
|
-
inventory: depositInventory,
|
|
277
|
-
};
|
|
278
|
-
expect(getDepositRequest()).toEqual(request);
|
|
279
|
-
});
|
|
280
|
-
it('unsets an unverified key before falling back to a PAT', async () => {
|
|
281
|
-
vi.mocked(openDiagnosticConnection).mockRejectedValue(new Error('Authentication policy excludes KEYPAIR'));
|
|
282
|
-
await expect((0, connectSnowflake_1.connectSnowflakeHandler)(options, getDependencies())).resolves.toBeUndefined();
|
|
283
|
-
expect(openDiagnosticConnection).toHaveBeenCalledTimes(3);
|
|
284
|
-
expect(sleep).toHaveBeenCalledTimes(2);
|
|
285
|
-
expect(sleep).toHaveBeenCalledWith(5_000);
|
|
286
|
-
expect(unsetUserPublicKey).toHaveBeenCalledWith(discovery.user, 'RSA_PUBLIC_KEY');
|
|
287
|
-
expect(createProgrammaticAccessToken).toHaveBeenCalledAfter(unsetUserPublicKey);
|
|
288
|
-
});
|
|
289
|
-
it('falls back to a PAT when key registration lacks privileges', async () => {
|
|
290
|
-
vi.mocked(setUserPublicKey).mockRejectedValue(new Error('Insufficient privileges to operate on user'));
|
|
291
|
-
await expect((0, connectSnowflake_1.connectSnowflakeHandler)(options, getDependencies())).resolves.toBeUndefined();
|
|
292
|
-
expect(createProgrammaticAccessToken).toHaveBeenCalledWith(expect.stringMatching(/^LIGHTDASH_ONBOARDING_\d+$/), 365, 60);
|
|
293
|
-
expect(write).toHaveBeenCalledWith('Secured with a programmatic access token (expires 2027-07-14)');
|
|
294
|
-
expect(write).toHaveBeenCalledWith(expect.stringContaining('bypasses your Snowflake network policy for the next 60 minutes'));
|
|
295
|
-
});
|
|
296
|
-
it('prints administrator remediation when both durable paths fail', async () => {
|
|
297
|
-
vi.mocked(setUserPublicKey).mockRejectedValue(new Error('Insufficient privileges'));
|
|
298
|
-
vi.mocked(createProgrammaticAccessToken).mockRejectedValue(new Error('Authentication policy does not allow PROGRAMMATIC_ACCESS_TOKEN'));
|
|
299
|
-
await expect((0, connectSnowflake_1.connectSnowflakeHandler)(options, getDependencies())).rejects.toThrow('Snowflake programmatic access token creation failed');
|
|
300
|
-
expect(write).toHaveBeenCalledWith('GRANT MODIFY PROGRAMMATIC AUTHENTICATION METHODS ON USER lightdash_user TO ROLE lightdash_role;');
|
|
301
|
-
expect(write).toHaveBeenCalledWith(expect.stringContaining('PROGRAMMATIC_ACCESS_TOKEN'));
|
|
302
|
-
expect(fetchMock).not.toHaveBeenCalled();
|
|
303
|
-
});
|
|
304
|
-
it('reports an expired connect code without exposing it', async () => {
|
|
305
|
-
vi.mocked(fetchMock).mockResolvedValue(new node_fetch_1.Response(JSON.stringify({ status: 'error' }), {
|
|
306
|
-
status: 404,
|
|
307
|
-
headers: { 'Content-Type': 'application/json' },
|
|
308
|
-
}));
|
|
309
|
-
await expect((0, connectSnowflake_1.connectSnowflakeHandler)(options, getDependencies())).rejects.toThrow(common_1.WarehouseConnectionError);
|
|
310
|
-
expect(write).not.toHaveBeenCalledWith(expect.stringContaining(options.code));
|
|
311
|
-
const { LightdashAnalytics } = await Promise.resolve().then(() => tslib_1.__importStar(require('../analytics/analytics')));
|
|
312
|
-
expect(vi.mocked(LightdashAnalytics.track)).toHaveBeenCalledWith({
|
|
313
|
-
event: 'connect_snowflake.error',
|
|
314
|
-
properties: {
|
|
315
|
-
error: expect.any(String),
|
|
316
|
-
errorCategory: 'warehouse_connection',
|
|
317
|
-
},
|
|
318
|
-
});
|
|
319
|
-
});
|
|
320
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fileNames.test.d.ts","sourceRoot":"","sources":["../../../src/handlers/contentAsCode/fileNames.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const crypto_1 = require("crypto");
|
|
4
|
-
const vitest_1 = require("vitest");
|
|
5
|
-
const fileNames_1 = require("./fileNames");
|
|
6
|
-
(0, vitest_1.describe)('content-as-code filenames', () => {
|
|
7
|
-
(0, vitest_1.it)('normalizes unicode and preserves compatibility extensions', () => {
|
|
8
|
-
(0, vitest_1.expect)((0, fileNames_1.allocateContentFileNames)({
|
|
9
|
-
items: [{ identity: 'malaga', displayName: 'Málaga Finance' }],
|
|
10
|
-
fallbackPrefix: 'group',
|
|
11
|
-
extension: '.space.yml',
|
|
12
|
-
})).toStrictEqual(['malaga-finance.space.yml']);
|
|
13
|
-
});
|
|
14
|
-
(0, vitest_1.it)('uses stable identities for unicode-only names and collisions', () => {
|
|
15
|
-
const hash = (0, crypto_1.createHash)('sha256')
|
|
16
|
-
.update('party')
|
|
17
|
-
.digest('hex')
|
|
18
|
-
.slice(0, 8);
|
|
19
|
-
(0, vitest_1.expect)((0, fileNames_1.allocateContentFileNames)({
|
|
20
|
-
items: [{ identity: 'party', displayName: '🎉' }],
|
|
21
|
-
fallbackPrefix: 'group',
|
|
22
|
-
})).toStrictEqual([`group-${hash}.yml`]);
|
|
23
|
-
const names = (0, fileNames_1.allocateContentFileNames)({
|
|
24
|
-
items: [
|
|
25
|
-
{ identity: 'one', displayName: 'Finance' },
|
|
26
|
-
{ identity: 'two', displayName: 'finance' },
|
|
27
|
-
],
|
|
28
|
-
fallbackPrefix: 'group',
|
|
29
|
-
});
|
|
30
|
-
(0, vitest_1.expect)(new Set(names.map((name) => name.toLowerCase())).size).toBe(2);
|
|
31
|
-
});
|
|
32
|
-
(0, vitest_1.it)('bounds long stems while retaining a stable collision suffix', () => {
|
|
33
|
-
const names = (0, fileNames_1.allocateContentFileNames)({
|
|
34
|
-
items: [
|
|
35
|
-
{ identity: 'one', displayName: 'a'.repeat(500) },
|
|
36
|
-
{ identity: 'two', displayName: 'a'.repeat(500) },
|
|
37
|
-
],
|
|
38
|
-
fallbackPrefix: 'chart',
|
|
39
|
-
});
|
|
40
|
-
(0, vitest_1.expect)(names.every((name) => name.length <= 204)).toBe(true);
|
|
41
|
-
(0, vitest_1.expect)(names[0]).not.toBe(names[1]);
|
|
42
|
-
});
|
|
43
|
-
(0, vitest_1.it)('preserves SQL and URI-encoded compatibility profiles', () => {
|
|
44
|
-
(0, vitest_1.expect)((0, fileNames_1.allocateContentFileNames)({
|
|
45
|
-
items: [
|
|
46
|
-
{
|
|
47
|
-
identity: 'orders',
|
|
48
|
-
displayName: 'Orders',
|
|
49
|
-
preferredFileName: 'orders.sql.yml',
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
fallbackPrefix: 'sql-chart',
|
|
53
|
-
extension: '.sql.yml',
|
|
54
|
-
})).toStrictEqual(['orders.sql.yml']);
|
|
55
|
-
(0, vitest_1.expect)((0, fileNames_1.allocateContentFileNames)({
|
|
56
|
-
items: [
|
|
57
|
-
{
|
|
58
|
-
identity: 'finance/view',
|
|
59
|
-
displayName: 'Finance view',
|
|
60
|
-
preferredFileName: 'finance%2Fview.yml',
|
|
61
|
-
},
|
|
62
|
-
],
|
|
63
|
-
fallbackPrefix: 'virtual-view',
|
|
64
|
-
})).toStrictEqual(['finance%2Fview.yml']);
|
|
65
|
-
});
|
|
66
|
-
(0, vitest_1.it)('reuses an existing file owned by the same identity', () => {
|
|
67
|
-
(0, vitest_1.expect)((0, fileNames_1.allocateContentFileNames)({
|
|
68
|
-
items: [{ identity: 'finance', displayName: 'New name' }],
|
|
69
|
-
fallbackPrefix: 'group',
|
|
70
|
-
existingFileNameByIdentity: new Map([
|
|
71
|
-
['finance', 'user-owned-name.yaml'],
|
|
72
|
-
]),
|
|
73
|
-
})).toStrictEqual(['user-owned-name.yaml']);
|
|
74
|
-
});
|
|
75
|
-
(0, vitest_1.it)('rejects absolute and parent-traversal paths', () => {
|
|
76
|
-
(0, vitest_1.expect)(() => (0, fileNames_1.assertSafeContentFilePath)('../secrets.yml')).toThrow('Unsafe');
|
|
77
|
-
(0, vitest_1.expect)(() => (0, fileNames_1.assertSafeContentFilePath)('/tmp/file.yml')).toThrow('Unsafe');
|
|
78
|
-
});
|
|
79
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"registry.test.d.ts","sourceRoot":"","sources":["../../../src/handlers/contentAsCode/registry.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vitest_1 = require("vitest");
|
|
4
|
-
const registry_1 = require("./registry");
|
|
5
|
-
(0, vitest_1.describe)('content-as-code resource registry', () => {
|
|
6
|
-
(0, vitest_1.it)('keeps organization dependencies in a valid order', () => {
|
|
7
|
-
(0, vitest_1.expect)(() => (0, registry_1.assertCodeResourceDependencyOrder)(registry_1.ORGANIZATION_CODE_RESOURCES)).not.toThrow();
|
|
8
|
-
});
|
|
9
|
-
(0, vitest_1.it)('keeps project dependencies in a valid order', () => {
|
|
10
|
-
(0, vitest_1.expect)(() => (0, registry_1.assertCodeResourceDependencyOrder)(registry_1.PROJECT_CODE_RESOURCES)).not.toThrow();
|
|
11
|
-
});
|
|
12
|
-
(0, vitest_1.it)('rejects resources registered before their dependencies', () => {
|
|
13
|
-
(0, vitest_1.expect)(() => (0, registry_1.assertCodeResourceDependencyOrder)([
|
|
14
|
-
{ kind: 'group', dependencies: ['user'] },
|
|
15
|
-
{ kind: 'user', dependencies: [] },
|
|
16
|
-
])).toThrow('group');
|
|
17
|
-
});
|
|
18
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resource.test.d.ts","sourceRoot":"","sources":["../../../src/handlers/contentAsCode/resource.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const tslib_1 = require("tslib");
|
|
4
|
-
const common_1 = require("@lightdash/common");
|
|
5
|
-
const fs_1 = require("fs");
|
|
6
|
-
const os_1 = tslib_1.__importDefault(require("os"));
|
|
7
|
-
const path_1 = tslib_1.__importDefault(require("path"));
|
|
8
|
-
const vitest_1 = require("vitest");
|
|
9
|
-
const projectResources_1 = require("./projectResources");
|
|
10
|
-
const resource_1 = require("./resource");
|
|
11
|
-
const temporaryDirectories = [];
|
|
12
|
-
const agent = (slug) => ({
|
|
13
|
-
contentType: common_1.ContentAsCodeType.AI_AGENT,
|
|
14
|
-
version: 1,
|
|
15
|
-
agentVersion: 2,
|
|
16
|
-
slug,
|
|
17
|
-
name: slug,
|
|
18
|
-
description: null,
|
|
19
|
-
imageUrl: null,
|
|
20
|
-
instruction: null,
|
|
21
|
-
tags: null,
|
|
22
|
-
enableDataAccess: true,
|
|
23
|
-
enableSelfImprovement: false,
|
|
24
|
-
enableContentTools: false,
|
|
25
|
-
enableUserContext: false,
|
|
26
|
-
modelConfig: null,
|
|
27
|
-
});
|
|
28
|
-
(0, vitest_1.afterEach)(async () => {
|
|
29
|
-
await Promise.all(temporaryDirectories.splice(0).map((directory) => fs_1.promises.rm(directory, {
|
|
30
|
-
recursive: true,
|
|
31
|
-
force: true,
|
|
32
|
-
})));
|
|
33
|
-
});
|
|
34
|
-
(0, vitest_1.describe)('content-as-code resource files', () => {
|
|
35
|
-
(0, vitest_1.it)('round trips exact homepage names safely and rejects duplicate local identities', async () => {
|
|
36
|
-
const basePath = await fs_1.promises.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'lightdash-homepage-code-'));
|
|
37
|
-
temporaryDirectories.push(basePath);
|
|
38
|
-
const document = {
|
|
39
|
-
contentType: common_1.ContentAsCodeType.HOMEPAGE,
|
|
40
|
-
version: 1,
|
|
41
|
-
name: '../Home / 100%',
|
|
42
|
-
config: { version: 1, rows: [] },
|
|
43
|
-
publication: null,
|
|
44
|
-
};
|
|
45
|
-
await (0, resource_1.writeCodeResourceDocuments)({
|
|
46
|
-
definition: projectResources_1.HOMEPAGE_CODE_RESOURCE,
|
|
47
|
-
basePath,
|
|
48
|
-
documents: [document],
|
|
49
|
-
pruneOtherDocuments: true,
|
|
50
|
-
});
|
|
51
|
-
const fileNames = await fs_1.promises.readdir(path_1.default.join(basePath, 'homepages'));
|
|
52
|
-
(0, vitest_1.expect)(fileNames).toEqual(['..%2FHome %2F 100%25.yml']);
|
|
53
|
-
const result = await (0, resource_1.readCodeResourceFiles)({
|
|
54
|
-
definition: projectResources_1.HOMEPAGE_CODE_RESOURCE,
|
|
55
|
-
basePath,
|
|
56
|
-
});
|
|
57
|
-
(0, vitest_1.expect)(result.files[0].document).toEqual(document);
|
|
58
|
-
await fs_1.promises.copyFile(path_1.default.join(basePath, 'homepages', fileNames[0]), path_1.default.join(basePath, 'homepages', 'duplicate.yaml'));
|
|
59
|
-
const duplicates = await (0, resource_1.readCodeResourceFiles)({
|
|
60
|
-
definition: projectResources_1.HOMEPAGE_CODE_RESOURCE,
|
|
61
|
-
basePath,
|
|
62
|
-
});
|
|
63
|
-
(0, vitest_1.expect)(duplicates.files).toEqual([]);
|
|
64
|
-
(0, vitest_1.expect)(duplicates.failures[0].message).toContain('Duplicate');
|
|
65
|
-
});
|
|
66
|
-
(0, vitest_1.it)('preserves other documents when writing a filtered download', async () => {
|
|
67
|
-
const basePath = await fs_1.promises.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'lightdash-content-as-code-'));
|
|
68
|
-
temporaryDirectories.push(basePath);
|
|
69
|
-
await (0, resource_1.writeCodeResourceDocuments)({
|
|
70
|
-
definition: projectResources_1.AI_AGENT_CODE_RESOURCE,
|
|
71
|
-
basePath,
|
|
72
|
-
documents: [agent('alpha'), agent('beta')],
|
|
73
|
-
pruneOtherDocuments: true,
|
|
74
|
-
});
|
|
75
|
-
await (0, resource_1.writeCodeResourceDocuments)({
|
|
76
|
-
definition: projectResources_1.AI_AGENT_CODE_RESOURCE,
|
|
77
|
-
basePath,
|
|
78
|
-
documents: [agent('alpha')],
|
|
79
|
-
pruneOtherDocuments: false,
|
|
80
|
-
});
|
|
81
|
-
await (0, vitest_1.expect)(fs_1.promises.readdir(path_1.default.join(basePath, 'ai-agents'))).resolves.toEqual(['alpha.yml', 'beta.yml']);
|
|
82
|
-
});
|
|
83
|
-
(0, vitest_1.it)('prunes other documents when writing a complete download', async () => {
|
|
84
|
-
const basePath = await fs_1.promises.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'lightdash-content-as-code-'));
|
|
85
|
-
temporaryDirectories.push(basePath);
|
|
86
|
-
await (0, resource_1.writeCodeResourceDocuments)({
|
|
87
|
-
definition: projectResources_1.AI_AGENT_CODE_RESOURCE,
|
|
88
|
-
basePath,
|
|
89
|
-
documents: [agent('alpha'), agent('beta')],
|
|
90
|
-
pruneOtherDocuments: true,
|
|
91
|
-
});
|
|
92
|
-
await (0, resource_1.writeCodeResourceDocuments)({
|
|
93
|
-
definition: projectResources_1.AI_AGENT_CODE_RESOURCE,
|
|
94
|
-
basePath,
|
|
95
|
-
documents: [agent('alpha')],
|
|
96
|
-
pruneOtherDocuments: true,
|
|
97
|
-
});
|
|
98
|
-
await (0, vitest_1.expect)(fs_1.promises.readdir(path_1.default.join(basePath, 'ai-agents'))).resolves.toEqual(['alpha.yml']);
|
|
99
|
-
});
|
|
100
|
-
(0, vitest_1.it)('ignores other scheduled content types in a shared legacy folder', async () => {
|
|
101
|
-
const basePath = await fs_1.promises.mkdtemp(path_1.default.join(os_1.default.tmpdir(), 'lightdash-content-as-code-'));
|
|
102
|
-
temporaryDirectories.push(basePath);
|
|
103
|
-
const alertFolder = path_1.default.join(basePath, 'alerts', 'charts', 'orders');
|
|
104
|
-
await fs_1.promises.mkdir(alertFolder, { recursive: true });
|
|
105
|
-
await Promise.all([
|
|
106
|
-
fs_1.promises.writeFile(path_1.default.join(alertFolder, 'alert.yml'), 'contentType: alert\nversion: 1\nslug: revenue-alert\nname: Revenue alert\n'),
|
|
107
|
-
fs_1.promises.writeFile(path_1.default.join(alertFolder, 'delivery.yml'), 'contentType: scheduled_delivery\nversion: 1\nslug: revenue-delivery\nname: Revenue delivery\n'),
|
|
108
|
-
fs_1.promises.writeFile(path_1.default.join(alertFolder, 'invalid-alert.yml'), 'contentType: alert\nslug: invalid-alert\nname: Invalid alert\n'),
|
|
109
|
-
]);
|
|
110
|
-
const result = await (0, resource_1.readCodeResourceFiles)({
|
|
111
|
-
definition: projectResources_1.ALERT_CODE_RESOURCE,
|
|
112
|
-
basePath,
|
|
113
|
-
});
|
|
114
|
-
(0, vitest_1.expect)(result.files.map(({ document }) => document.slug)).toEqual([
|
|
115
|
-
'revenue-alert',
|
|
116
|
-
]);
|
|
117
|
-
(0, vitest_1.expect)(result.failures).toHaveLength(1);
|
|
118
|
-
(0, vitest_1.expect)(result.failures[0].message).toContain('invalid-alert.yml');
|
|
119
|
-
(0, vitest_1.expect)(result.failures[0].message).toContain('expected version 1');
|
|
120
|
-
});
|
|
121
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getDbtVersion.test.d.ts","sourceRoot":"","sources":["../../../src/handlers/dbt/getDbtVersion.test.ts"],"names":[],"mappings":""}
|