webpipe-js 2.0.21 → 2.0.23
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/index.cjs +159 -1
- package/dist/index.d.cts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.mjs +159 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -917,6 +917,85 @@ var Parser = class {
|
|
|
917
917
|
callTarget
|
|
918
918
|
};
|
|
919
919
|
}
|
|
920
|
+
if (field === "selector") {
|
|
921
|
+
const selectorStr = (() => {
|
|
922
|
+
const bt = this.tryParse(() => this.parseBacktickString());
|
|
923
|
+
if (bt !== null) return bt;
|
|
924
|
+
const qt = this.tryParse(() => this.parseQuotedString());
|
|
925
|
+
if (qt !== null) return qt;
|
|
926
|
+
throw new Error("selector requires quoted string");
|
|
927
|
+
})();
|
|
928
|
+
this.skipInlineSpaces();
|
|
929
|
+
const operation = this.consumeWhile((c) => c !== " " && c !== "\n");
|
|
930
|
+
this.skipInlineSpaces();
|
|
931
|
+
let domAssert;
|
|
932
|
+
let comparison2;
|
|
933
|
+
let value2;
|
|
934
|
+
if (operation === "exists") {
|
|
935
|
+
domAssert = { kind: "Exists" };
|
|
936
|
+
comparison2 = "exists";
|
|
937
|
+
value2 = "true";
|
|
938
|
+
} else if (operation === "does") {
|
|
939
|
+
this.expect("not");
|
|
940
|
+
this.skipInlineSpaces();
|
|
941
|
+
this.expect("exist");
|
|
942
|
+
domAssert = { kind: "Exists" };
|
|
943
|
+
comparison2 = "does_not_exist";
|
|
944
|
+
value2 = "false";
|
|
945
|
+
} else if (operation === "text") {
|
|
946
|
+
domAssert = { kind: "Text" };
|
|
947
|
+
this.skipInlineSpaces();
|
|
948
|
+
comparison2 = this.consumeWhile((c) => c !== " " && c !== "\n");
|
|
949
|
+
this.skipInlineSpaces();
|
|
950
|
+
value2 = (() => {
|
|
951
|
+
const v1 = this.tryParse(() => this.parseBacktickString());
|
|
952
|
+
if (v1 !== null) return v1;
|
|
953
|
+
const v2 = this.tryParse(() => this.parseQuotedString());
|
|
954
|
+
if (v2 !== null) return v2;
|
|
955
|
+
return this.consumeWhile((c) => c !== "\n");
|
|
956
|
+
})();
|
|
957
|
+
} else if (operation === "count") {
|
|
958
|
+
domAssert = { kind: "Count" };
|
|
959
|
+
let compParts = "";
|
|
960
|
+
while (this.pos < this.text.length && this.text[this.pos] !== "\n") {
|
|
961
|
+
const c = this.text[this.pos];
|
|
962
|
+
if (/\d/.test(c)) break;
|
|
963
|
+
compParts += c;
|
|
964
|
+
this.pos++;
|
|
965
|
+
}
|
|
966
|
+
comparison2 = compParts.trim();
|
|
967
|
+
value2 = this.consumeWhile((c) => c !== "\n").trim();
|
|
968
|
+
} else if (operation === "attribute") {
|
|
969
|
+
const attrName = (() => {
|
|
970
|
+
const bt = this.tryParse(() => this.parseBacktickString());
|
|
971
|
+
if (bt !== null) return bt;
|
|
972
|
+
const qt = this.tryParse(() => this.parseQuotedString());
|
|
973
|
+
if (qt !== null) return qt;
|
|
974
|
+
throw new Error("attribute requires quoted name");
|
|
975
|
+
})();
|
|
976
|
+
this.skipInlineSpaces();
|
|
977
|
+
comparison2 = this.consumeWhile((c) => c !== " " && c !== "\n");
|
|
978
|
+
this.skipInlineSpaces();
|
|
979
|
+
value2 = (() => {
|
|
980
|
+
const v1 = this.tryParse(() => this.parseBacktickString());
|
|
981
|
+
if (v1 !== null) return v1;
|
|
982
|
+
const v2 = this.tryParse(() => this.parseQuotedString());
|
|
983
|
+
if (v2 !== null) return v2;
|
|
984
|
+
return this.consumeWhile((c) => c !== "\n");
|
|
985
|
+
})();
|
|
986
|
+
domAssert = { kind: "Attribute", name: attrName };
|
|
987
|
+
} else {
|
|
988
|
+
throw new Error(`Unknown selector operation: ${operation}`);
|
|
989
|
+
}
|
|
990
|
+
return {
|
|
991
|
+
conditionType: ct,
|
|
992
|
+
field: "selector",
|
|
993
|
+
comparison: comparison2,
|
|
994
|
+
value: value2,
|
|
995
|
+
selector: selectorStr,
|
|
996
|
+
domAssert
|
|
997
|
+
};
|
|
998
|
+
}
|
|
920
999
|
let headerName;
|
|
921
1000
|
if (field === "header") {
|
|
922
1001
|
const h1 = this.tryParse(() => this.parseBacktickString());
|
|
@@ -971,6 +1050,36 @@ var Parser = class {
|
|
|
971
1050
|
parseAndMock() {
|
|
972
1051
|
return this.parseMockHead("and");
|
|
973
1052
|
}
|
|
1053
|
+
parseLetBinding() {
|
|
1054
|
+
this.expect("let");
|
|
1055
|
+
this.skipInlineSpaces();
|
|
1056
|
+
const name = this.parseIdentifier();
|
|
1057
|
+
this.skipInlineSpaces();
|
|
1058
|
+
this.expect("=");
|
|
1059
|
+
this.skipInlineSpaces();
|
|
1060
|
+
const value = (() => {
|
|
1061
|
+
const bt = this.tryParse(() => this.parseBacktickString());
|
|
1062
|
+
if (bt !== null) return bt;
|
|
1063
|
+
const qt = this.tryParse(() => this.parseQuotedString());
|
|
1064
|
+
if (qt !== null) return qt;
|
|
1065
|
+
if (this.text.startsWith("true", this.pos)) {
|
|
1066
|
+
this.pos += 4;
|
|
1067
|
+
return "true";
|
|
1068
|
+
}
|
|
1069
|
+
if (this.text.startsWith("false", this.pos)) {
|
|
1070
|
+
this.pos += 5;
|
|
1071
|
+
return "false";
|
|
1072
|
+
}
|
|
1073
|
+
const num = this.tryParse(() => {
|
|
1074
|
+
const digits = this.consumeWhile((c) => /[0-9]/.test(c));
|
|
1075
|
+
if (digits.length === 0) throw new Error("number");
|
|
1076
|
+
return digits;
|
|
1077
|
+
});
|
|
1078
|
+
if (num !== null) return num;
|
|
1079
|
+
throw new Error("let value");
|
|
1080
|
+
})();
|
|
1081
|
+
return [name, value];
|
|
1082
|
+
}
|
|
974
1083
|
parseIt() {
|
|
975
1084
|
this.skipSpaces();
|
|
976
1085
|
this.expect("it");
|
|
@@ -989,12 +1098,22 @@ var Parser = class {
|
|
|
989
1098
|
this.skipInlineSpaces();
|
|
990
1099
|
const when = this.parseWhen();
|
|
991
1100
|
this.skipSpaces();
|
|
1101
|
+
const variables = [];
|
|
992
1102
|
let input;
|
|
993
1103
|
let body;
|
|
994
1104
|
let headers;
|
|
995
1105
|
let cookies;
|
|
996
1106
|
let firstWithClause = true;
|
|
997
1107
|
while (true) {
|
|
1108
|
+
const letBinding = this.tryParse(() => {
|
|
1109
|
+
const binding = this.parseLetBinding();
|
|
1110
|
+
this.skipSpaces();
|
|
1111
|
+
return binding;
|
|
1112
|
+
});
|
|
1113
|
+
if (letBinding) {
|
|
1114
|
+
variables.push(letBinding);
|
|
1115
|
+
continue;
|
|
1116
|
+
}
|
|
998
1117
|
const parsed = this.tryParse(() => {
|
|
999
1118
|
if (firstWithClause) {
|
|
1000
1119
|
this.expect("with");
|
|
@@ -1054,7 +1173,17 @@ var Parser = class {
|
|
|
1054
1173
|
if (!c) break;
|
|
1055
1174
|
conditions.push(c);
|
|
1056
1175
|
}
|
|
1057
|
-
return {
|
|
1176
|
+
return {
|
|
1177
|
+
name,
|
|
1178
|
+
mocks: [...mocks, ...extraMocks],
|
|
1179
|
+
when,
|
|
1180
|
+
variables: variables.length > 0 ? variables : void 0,
|
|
1181
|
+
input,
|
|
1182
|
+
body,
|
|
1183
|
+
headers,
|
|
1184
|
+
cookies,
|
|
1185
|
+
conditions
|
|
1186
|
+
};
|
|
1058
1187
|
}
|
|
1059
1188
|
parseDescribe() {
|
|
1060
1189
|
this.skipSpaces();
|
|
@@ -1199,6 +1328,24 @@ function printMock(mock, indent = " ") {
|
|
|
1199
1328
|
}
|
|
1200
1329
|
function printCondition(condition, indent = " ") {
|
|
1201
1330
|
const condType = condition.conditionType.toLowerCase();
|
|
1331
|
+
if (condition.field === "selector" && condition.selector && condition.domAssert) {
|
|
1332
|
+
const selector = condition.selector;
|
|
1333
|
+
const formatValue = (val) => {
|
|
1334
|
+
if (val.startsWith("`") || val.startsWith('"')) return val;
|
|
1335
|
+
if (val.includes("\n") || val.includes("{") || val.includes("[")) return `\`${val}\``;
|
|
1336
|
+
return `"${val}"`;
|
|
1337
|
+
};
|
|
1338
|
+
if (condition.domAssert.kind === "Exists") {
|
|
1339
|
+
const operation = condition.comparison === "exists" ? "exists" : "does not exist";
|
|
1340
|
+
return `${indent}${condType} selector "${selector}" ${operation}`;
|
|
1341
|
+
} else if (condition.domAssert.kind === "Text") {
|
|
1342
|
+
return `${indent}${condType} selector "${selector}" text ${condition.comparison} ${formatValue(condition.value)}`;
|
|
1343
|
+
} else if (condition.domAssert.kind === "Count") {
|
|
1344
|
+
return `${indent}${condType} selector "${selector}" count ${condition.comparison} ${condition.value}`;
|
|
1345
|
+
} else if (condition.domAssert.kind === "Attribute") {
|
|
1346
|
+
return `${indent}${condType} selector "${selector}" attribute "${condition.domAssert.name}" ${condition.comparison} ${formatValue(condition.value)}`;
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1202
1349
|
const fieldPart = condition.headerName ? `${condition.field} "${condition.headerName}"` : condition.jqExpr ? `${condition.field} \`${condition.jqExpr}\`` : condition.field;
|
|
1203
1350
|
const value = condition.value.startsWith("`") ? condition.value : condition.value.includes("\n") || condition.value.includes("{") || condition.value.includes("[") ? `\`${condition.value}\`` : condition.value;
|
|
1204
1351
|
return `${indent}${condType} ${fieldPart} ${condition.comparison} ${value}`;
|
|
@@ -1210,6 +1357,17 @@ function printTest(test) {
|
|
|
1210
1357
|
lines.push(printMock(mock, " "));
|
|
1211
1358
|
});
|
|
1212
1359
|
lines.push(` when ${formatWhen(test.when)}`);
|
|
1360
|
+
if (test.variables) {
|
|
1361
|
+
test.variables.forEach(([name, value]) => {
|
|
1362
|
+
const formattedValue = (() => {
|
|
1363
|
+
if (value.startsWith("`") || value.startsWith('"')) return value;
|
|
1364
|
+
if (value === "true" || value === "false" || /^\d+$/.test(value)) return value;
|
|
1365
|
+
if (value.includes("{") || value.includes("[") || value.includes("\n")) return `\`${value}\``;
|
|
1366
|
+
return `"${value}"`;
|
|
1367
|
+
})();
|
|
1368
|
+
lines.push(` let ${name} = ${formattedValue}`);
|
|
1369
|
+
});
|
|
1370
|
+
}
|
|
1213
1371
|
if (test.input) {
|
|
1214
1372
|
lines.push(` with input \`${test.input}\``);
|
|
1215
1373
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -162,6 +162,7 @@ interface It {
|
|
|
162
162
|
name: string;
|
|
163
163
|
mocks: Mock[];
|
|
164
164
|
when: When;
|
|
165
|
+
variables?: Array<[string, string]>;
|
|
165
166
|
input?: string;
|
|
166
167
|
body?: string;
|
|
167
168
|
headers?: string;
|
|
@@ -180,6 +181,16 @@ type When = {
|
|
|
180
181
|
varType: string;
|
|
181
182
|
name: string;
|
|
182
183
|
};
|
|
184
|
+
type DomAssertType = {
|
|
185
|
+
kind: 'Exists';
|
|
186
|
+
} | {
|
|
187
|
+
kind: 'Text';
|
|
188
|
+
} | {
|
|
189
|
+
kind: 'Count';
|
|
190
|
+
} | {
|
|
191
|
+
kind: 'Attribute';
|
|
192
|
+
name: string;
|
|
193
|
+
};
|
|
183
194
|
interface Condition {
|
|
184
195
|
conditionType: 'Then' | 'And';
|
|
185
196
|
field: string;
|
|
@@ -189,6 +200,8 @@ interface Condition {
|
|
|
189
200
|
value: string;
|
|
190
201
|
isCallAssertion?: boolean;
|
|
191
202
|
callTarget?: string;
|
|
203
|
+
selector?: string;
|
|
204
|
+
domAssert?: DomAssertType;
|
|
192
205
|
}
|
|
193
206
|
type DiagnosticSeverity = 'error' | 'warning' | 'info';
|
|
194
207
|
interface ParseDiagnostic {
|
|
@@ -232,4 +245,4 @@ declare function formatTagExpr(expr: TagExpr): string;
|
|
|
232
245
|
declare function formatPipelineRef(ref: PipelineRef): string[];
|
|
233
246
|
declare function formatWhen(when: When): string;
|
|
234
247
|
|
|
235
|
-
export { type Comment, type Condition, type Config, type ConfigProperty, type ConfigType, type ConfigValue, type Describe, type DiagnosticSeverity, type DispatchBranch, type GraphQLSchema, type It, type Mock, type MutationResolver, type NamedPipeline, type ParseDiagnostic, type Pipeline, type PipelineRef, type PipelineStep, type Program, type QueryResolver, type ResultBranch, type ResultBranchType, type Route, type Tag, type TagExpr, type Variable, type When, formatConfigValue, formatPipelineRef, formatPipelineStep, formatStepConfig, formatTag, formatTagExpr, formatTags, formatWhen, getPipelineRanges, getVariableRanges, parseProgram, parseProgramWithDiagnostics, prettyPrint, printComment, printCondition, printConfig, printDescribe, printGraphQLSchema, printMock, printMutationResolver, printPipeline, printQueryResolver, printRoute, printTest, printVariable };
|
|
248
|
+
export { type Comment, type Condition, type Config, type ConfigProperty, type ConfigType, type ConfigValue, type Describe, type DiagnosticSeverity, type DispatchBranch, type DomAssertType, type GraphQLSchema, type It, type Mock, type MutationResolver, type NamedPipeline, type ParseDiagnostic, type Pipeline, type PipelineRef, type PipelineStep, type Program, type QueryResolver, type ResultBranch, type ResultBranchType, type Route, type Tag, type TagExpr, type Variable, type When, formatConfigValue, formatPipelineRef, formatPipelineStep, formatStepConfig, formatTag, formatTagExpr, formatTags, formatWhen, getPipelineRanges, getVariableRanges, parseProgram, parseProgramWithDiagnostics, prettyPrint, printComment, printCondition, printConfig, printDescribe, printGraphQLSchema, printMock, printMutationResolver, printPipeline, printQueryResolver, printRoute, printTest, printVariable };
|
package/dist/index.d.ts
CHANGED
|
@@ -162,6 +162,7 @@ interface It {
|
|
|
162
162
|
name: string;
|
|
163
163
|
mocks: Mock[];
|
|
164
164
|
when: When;
|
|
165
|
+
variables?: Array<[string, string]>;
|
|
165
166
|
input?: string;
|
|
166
167
|
body?: string;
|
|
167
168
|
headers?: string;
|
|
@@ -180,6 +181,16 @@ type When = {
|
|
|
180
181
|
varType: string;
|
|
181
182
|
name: string;
|
|
182
183
|
};
|
|
184
|
+
type DomAssertType = {
|
|
185
|
+
kind: 'Exists';
|
|
186
|
+
} | {
|
|
187
|
+
kind: 'Text';
|
|
188
|
+
} | {
|
|
189
|
+
kind: 'Count';
|
|
190
|
+
} | {
|
|
191
|
+
kind: 'Attribute';
|
|
192
|
+
name: string;
|
|
193
|
+
};
|
|
183
194
|
interface Condition {
|
|
184
195
|
conditionType: 'Then' | 'And';
|
|
185
196
|
field: string;
|
|
@@ -189,6 +200,8 @@ interface Condition {
|
|
|
189
200
|
value: string;
|
|
190
201
|
isCallAssertion?: boolean;
|
|
191
202
|
callTarget?: string;
|
|
203
|
+
selector?: string;
|
|
204
|
+
domAssert?: DomAssertType;
|
|
192
205
|
}
|
|
193
206
|
type DiagnosticSeverity = 'error' | 'warning' | 'info';
|
|
194
207
|
interface ParseDiagnostic {
|
|
@@ -232,4 +245,4 @@ declare function formatTagExpr(expr: TagExpr): string;
|
|
|
232
245
|
declare function formatPipelineRef(ref: PipelineRef): string[];
|
|
233
246
|
declare function formatWhen(when: When): string;
|
|
234
247
|
|
|
235
|
-
export { type Comment, type Condition, type Config, type ConfigProperty, type ConfigType, type ConfigValue, type Describe, type DiagnosticSeverity, type DispatchBranch, type GraphQLSchema, type It, type Mock, type MutationResolver, type NamedPipeline, type ParseDiagnostic, type Pipeline, type PipelineRef, type PipelineStep, type Program, type QueryResolver, type ResultBranch, type ResultBranchType, type Route, type Tag, type TagExpr, type Variable, type When, formatConfigValue, formatPipelineRef, formatPipelineStep, formatStepConfig, formatTag, formatTagExpr, formatTags, formatWhen, getPipelineRanges, getVariableRanges, parseProgram, parseProgramWithDiagnostics, prettyPrint, printComment, printCondition, printConfig, printDescribe, printGraphQLSchema, printMock, printMutationResolver, printPipeline, printQueryResolver, printRoute, printTest, printVariable };
|
|
248
|
+
export { type Comment, type Condition, type Config, type ConfigProperty, type ConfigType, type ConfigValue, type Describe, type DiagnosticSeverity, type DispatchBranch, type DomAssertType, type GraphQLSchema, type It, type Mock, type MutationResolver, type NamedPipeline, type ParseDiagnostic, type Pipeline, type PipelineRef, type PipelineStep, type Program, type QueryResolver, type ResultBranch, type ResultBranchType, type Route, type Tag, type TagExpr, type Variable, type When, formatConfigValue, formatPipelineRef, formatPipelineStep, formatStepConfig, formatTag, formatTagExpr, formatTags, formatWhen, getPipelineRanges, getVariableRanges, parseProgram, parseProgramWithDiagnostics, prettyPrint, printComment, printCondition, printConfig, printDescribe, printGraphQLSchema, printMock, printMutationResolver, printPipeline, printQueryResolver, printRoute, printTest, printVariable };
|
package/dist/index.mjs
CHANGED
|
@@ -867,6 +867,85 @@ var Parser = class {
|
|
|
867
867
|
callTarget
|
|
868
868
|
};
|
|
869
869
|
}
|
|
870
|
+
if (field === "selector") {
|
|
871
|
+
const selectorStr = (() => {
|
|
872
|
+
const bt = this.tryParse(() => this.parseBacktickString());
|
|
873
|
+
if (bt !== null) return bt;
|
|
874
|
+
const qt = this.tryParse(() => this.parseQuotedString());
|
|
875
|
+
if (qt !== null) return qt;
|
|
876
|
+
throw new Error("selector requires quoted string");
|
|
877
|
+
})();
|
|
878
|
+
this.skipInlineSpaces();
|
|
879
|
+
const operation = this.consumeWhile((c) => c !== " " && c !== "\n");
|
|
880
|
+
this.skipInlineSpaces();
|
|
881
|
+
let domAssert;
|
|
882
|
+
let comparison2;
|
|
883
|
+
let value2;
|
|
884
|
+
if (operation === "exists") {
|
|
885
|
+
domAssert = { kind: "Exists" };
|
|
886
|
+
comparison2 = "exists";
|
|
887
|
+
value2 = "true";
|
|
888
|
+
} else if (operation === "does") {
|
|
889
|
+
this.expect("not");
|
|
890
|
+
this.skipInlineSpaces();
|
|
891
|
+
this.expect("exist");
|
|
892
|
+
domAssert = { kind: "Exists" };
|
|
893
|
+
comparison2 = "does_not_exist";
|
|
894
|
+
value2 = "false";
|
|
895
|
+
} else if (operation === "text") {
|
|
896
|
+
domAssert = { kind: "Text" };
|
|
897
|
+
this.skipInlineSpaces();
|
|
898
|
+
comparison2 = this.consumeWhile((c) => c !== " " && c !== "\n");
|
|
899
|
+
this.skipInlineSpaces();
|
|
900
|
+
value2 = (() => {
|
|
901
|
+
const v1 = this.tryParse(() => this.parseBacktickString());
|
|
902
|
+
if (v1 !== null) return v1;
|
|
903
|
+
const v2 = this.tryParse(() => this.parseQuotedString());
|
|
904
|
+
if (v2 !== null) return v2;
|
|
905
|
+
return this.consumeWhile((c) => c !== "\n");
|
|
906
|
+
})();
|
|
907
|
+
} else if (operation === "count") {
|
|
908
|
+
domAssert = { kind: "Count" };
|
|
909
|
+
let compParts = "";
|
|
910
|
+
while (this.pos < this.text.length && this.text[this.pos] !== "\n") {
|
|
911
|
+
const c = this.text[this.pos];
|
|
912
|
+
if (/\d/.test(c)) break;
|
|
913
|
+
compParts += c;
|
|
914
|
+
this.pos++;
|
|
915
|
+
}
|
|
916
|
+
comparison2 = compParts.trim();
|
|
917
|
+
value2 = this.consumeWhile((c) => c !== "\n").trim();
|
|
918
|
+
} else if (operation === "attribute") {
|
|
919
|
+
const attrName = (() => {
|
|
920
|
+
const bt = this.tryParse(() => this.parseBacktickString());
|
|
921
|
+
if (bt !== null) return bt;
|
|
922
|
+
const qt = this.tryParse(() => this.parseQuotedString());
|
|
923
|
+
if (qt !== null) return qt;
|
|
924
|
+
throw new Error("attribute requires quoted name");
|
|
925
|
+
})();
|
|
926
|
+
this.skipInlineSpaces();
|
|
927
|
+
comparison2 = this.consumeWhile((c) => c !== " " && c !== "\n");
|
|
928
|
+
this.skipInlineSpaces();
|
|
929
|
+
value2 = (() => {
|
|
930
|
+
const v1 = this.tryParse(() => this.parseBacktickString());
|
|
931
|
+
if (v1 !== null) return v1;
|
|
932
|
+
const v2 = this.tryParse(() => this.parseQuotedString());
|
|
933
|
+
if (v2 !== null) return v2;
|
|
934
|
+
return this.consumeWhile((c) => c !== "\n");
|
|
935
|
+
})();
|
|
936
|
+
domAssert = { kind: "Attribute", name: attrName };
|
|
937
|
+
} else {
|
|
938
|
+
throw new Error(`Unknown selector operation: ${operation}`);
|
|
939
|
+
}
|
|
940
|
+
return {
|
|
941
|
+
conditionType: ct,
|
|
942
|
+
field: "selector",
|
|
943
|
+
comparison: comparison2,
|
|
944
|
+
value: value2,
|
|
945
|
+
selector: selectorStr,
|
|
946
|
+
domAssert
|
|
947
|
+
};
|
|
948
|
+
}
|
|
870
949
|
let headerName;
|
|
871
950
|
if (field === "header") {
|
|
872
951
|
const h1 = this.tryParse(() => this.parseBacktickString());
|
|
@@ -921,6 +1000,36 @@ var Parser = class {
|
|
|
921
1000
|
parseAndMock() {
|
|
922
1001
|
return this.parseMockHead("and");
|
|
923
1002
|
}
|
|
1003
|
+
parseLetBinding() {
|
|
1004
|
+
this.expect("let");
|
|
1005
|
+
this.skipInlineSpaces();
|
|
1006
|
+
const name = this.parseIdentifier();
|
|
1007
|
+
this.skipInlineSpaces();
|
|
1008
|
+
this.expect("=");
|
|
1009
|
+
this.skipInlineSpaces();
|
|
1010
|
+
const value = (() => {
|
|
1011
|
+
const bt = this.tryParse(() => this.parseBacktickString());
|
|
1012
|
+
if (bt !== null) return bt;
|
|
1013
|
+
const qt = this.tryParse(() => this.parseQuotedString());
|
|
1014
|
+
if (qt !== null) return qt;
|
|
1015
|
+
if (this.text.startsWith("true", this.pos)) {
|
|
1016
|
+
this.pos += 4;
|
|
1017
|
+
return "true";
|
|
1018
|
+
}
|
|
1019
|
+
if (this.text.startsWith("false", this.pos)) {
|
|
1020
|
+
this.pos += 5;
|
|
1021
|
+
return "false";
|
|
1022
|
+
}
|
|
1023
|
+
const num = this.tryParse(() => {
|
|
1024
|
+
const digits = this.consumeWhile((c) => /[0-9]/.test(c));
|
|
1025
|
+
if (digits.length === 0) throw new Error("number");
|
|
1026
|
+
return digits;
|
|
1027
|
+
});
|
|
1028
|
+
if (num !== null) return num;
|
|
1029
|
+
throw new Error("let value");
|
|
1030
|
+
})();
|
|
1031
|
+
return [name, value];
|
|
1032
|
+
}
|
|
924
1033
|
parseIt() {
|
|
925
1034
|
this.skipSpaces();
|
|
926
1035
|
this.expect("it");
|
|
@@ -939,12 +1048,22 @@ var Parser = class {
|
|
|
939
1048
|
this.skipInlineSpaces();
|
|
940
1049
|
const when = this.parseWhen();
|
|
941
1050
|
this.skipSpaces();
|
|
1051
|
+
const variables = [];
|
|
942
1052
|
let input;
|
|
943
1053
|
let body;
|
|
944
1054
|
let headers;
|
|
945
1055
|
let cookies;
|
|
946
1056
|
let firstWithClause = true;
|
|
947
1057
|
while (true) {
|
|
1058
|
+
const letBinding = this.tryParse(() => {
|
|
1059
|
+
const binding = this.parseLetBinding();
|
|
1060
|
+
this.skipSpaces();
|
|
1061
|
+
return binding;
|
|
1062
|
+
});
|
|
1063
|
+
if (letBinding) {
|
|
1064
|
+
variables.push(letBinding);
|
|
1065
|
+
continue;
|
|
1066
|
+
}
|
|
948
1067
|
const parsed = this.tryParse(() => {
|
|
949
1068
|
if (firstWithClause) {
|
|
950
1069
|
this.expect("with");
|
|
@@ -1004,7 +1123,17 @@ var Parser = class {
|
|
|
1004
1123
|
if (!c) break;
|
|
1005
1124
|
conditions.push(c);
|
|
1006
1125
|
}
|
|
1007
|
-
return {
|
|
1126
|
+
return {
|
|
1127
|
+
name,
|
|
1128
|
+
mocks: [...mocks, ...extraMocks],
|
|
1129
|
+
when,
|
|
1130
|
+
variables: variables.length > 0 ? variables : void 0,
|
|
1131
|
+
input,
|
|
1132
|
+
body,
|
|
1133
|
+
headers,
|
|
1134
|
+
cookies,
|
|
1135
|
+
conditions
|
|
1136
|
+
};
|
|
1008
1137
|
}
|
|
1009
1138
|
parseDescribe() {
|
|
1010
1139
|
this.skipSpaces();
|
|
@@ -1149,6 +1278,24 @@ function printMock(mock, indent = " ") {
|
|
|
1149
1278
|
}
|
|
1150
1279
|
function printCondition(condition, indent = " ") {
|
|
1151
1280
|
const condType = condition.conditionType.toLowerCase();
|
|
1281
|
+
if (condition.field === "selector" && condition.selector && condition.domAssert) {
|
|
1282
|
+
const selector = condition.selector;
|
|
1283
|
+
const formatValue = (val) => {
|
|
1284
|
+
if (val.startsWith("`") || val.startsWith('"')) return val;
|
|
1285
|
+
if (val.includes("\n") || val.includes("{") || val.includes("[")) return `\`${val}\``;
|
|
1286
|
+
return `"${val}"`;
|
|
1287
|
+
};
|
|
1288
|
+
if (condition.domAssert.kind === "Exists") {
|
|
1289
|
+
const operation = condition.comparison === "exists" ? "exists" : "does not exist";
|
|
1290
|
+
return `${indent}${condType} selector "${selector}" ${operation}`;
|
|
1291
|
+
} else if (condition.domAssert.kind === "Text") {
|
|
1292
|
+
return `${indent}${condType} selector "${selector}" text ${condition.comparison} ${formatValue(condition.value)}`;
|
|
1293
|
+
} else if (condition.domAssert.kind === "Count") {
|
|
1294
|
+
return `${indent}${condType} selector "${selector}" count ${condition.comparison} ${condition.value}`;
|
|
1295
|
+
} else if (condition.domAssert.kind === "Attribute") {
|
|
1296
|
+
return `${indent}${condType} selector "${selector}" attribute "${condition.domAssert.name}" ${condition.comparison} ${formatValue(condition.value)}`;
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1152
1299
|
const fieldPart = condition.headerName ? `${condition.field} "${condition.headerName}"` : condition.jqExpr ? `${condition.field} \`${condition.jqExpr}\`` : condition.field;
|
|
1153
1300
|
const value = condition.value.startsWith("`") ? condition.value : condition.value.includes("\n") || condition.value.includes("{") || condition.value.includes("[") ? `\`${condition.value}\`` : condition.value;
|
|
1154
1301
|
return `${indent}${condType} ${fieldPart} ${condition.comparison} ${value}`;
|
|
@@ -1160,6 +1307,17 @@ function printTest(test) {
|
|
|
1160
1307
|
lines.push(printMock(mock, " "));
|
|
1161
1308
|
});
|
|
1162
1309
|
lines.push(` when ${formatWhen(test.when)}`);
|
|
1310
|
+
if (test.variables) {
|
|
1311
|
+
test.variables.forEach(([name, value]) => {
|
|
1312
|
+
const formattedValue = (() => {
|
|
1313
|
+
if (value.startsWith("`") || value.startsWith('"')) return value;
|
|
1314
|
+
if (value === "true" || value === "false" || /^\d+$/.test(value)) return value;
|
|
1315
|
+
if (value.includes("{") || value.includes("[") || value.includes("\n")) return `\`${value}\``;
|
|
1316
|
+
return `"${value}"`;
|
|
1317
|
+
})();
|
|
1318
|
+
lines.push(` let ${name} = ${formattedValue}`);
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1163
1321
|
if (test.input) {
|
|
1164
1322
|
lines.push(` with input \`${test.input}\``);
|
|
1165
1323
|
}
|