@@ -16,6 +16,11 @@ import { getStageOperators } from '../helpers/read-stage-operators';
1616
1717const { expect } = chai ;
1818
19+ const OUT_STAGE_PREVIEW_TEXT =
20+ 'The $out operator will cause the pipeline to persist the results to the specified location (collection, S3, or Atlas). If the collection exists it will be replaced.' ;
21+ const MERGE_STAGE_PREVIEW_TEXT =
22+ 'The $merge operator will cause the pipeline to persist the results to the specified location.' ;
23+
1924async function waitForAnyText (
2025 browser : CompassBrowser ,
2126 element : Element < 'async' >
@@ -180,7 +185,9 @@ describe('Collection aggregations tab', function () {
180185 let browser : CompassBrowser ;
181186
182187 before ( async function ( ) {
183- compass = await beforeTests ( ) ;
188+ compass = await beforeTests ( {
189+ extraSpawnArgs : [ '--show-focus-mode' ] ,
190+ } ) ;
184191 browser = compass . browser ;
185192 } ) ;
186193
@@ -308,9 +315,7 @@ describe('Collection aggregations tab', function () {
308315 const text = await preview . getText ( ) ;
309316
310317 expect ( text ) . to . include ( 'Documents will be saved to test.listings.' ) ;
311- expect ( text ) . to . include (
312- 'The $out operator will cause the pipeline to persist the results to the specified location (collection, S3, or Atlas). If the collection exists it will be replaced.'
313- ) ;
318+ expect ( text ) . to . include ( OUT_STAGE_PREVIEW_TEXT ) ;
314319 } ) ;
315320
316321 it ( 'shows $merge stage preview' , async function ( ) {
@@ -326,9 +331,7 @@ describe('Collection aggregations tab', function () {
326331 const text = await preview . getText ( ) ;
327332
328333 expect ( text ) . to . include ( 'Documents will be saved to test.listings.' ) ;
329- expect ( text ) . to . include (
330- 'The $merge operator will cause the pipeline to persist the results to the specified location.'
331- ) ;
334+ expect ( text ) . to . include ( MERGE_STAGE_PREVIEW_TEXT ) ;
332335 } ) ;
333336
334337 it ( 'shows empty preview' , async function ( ) {
@@ -1093,6 +1096,228 @@ describe('Collection aggregations tab', function () {
10931096 } ) ;
10941097 } ) ;
10951098
1099+ describe ( 'focus mode' , function ( ) {
1100+ it ( 'opens and closes the modal' , async function ( ) {
1101+ await browser . selectStageOperator ( 0 , '$match' ) ;
1102+ await browser . setAceValue ( Selectors . stageEditor ( 0 ) , '{ i: 5 }' ) ;
1103+ await browser . clickVisible ( Selectors . stageFocusModeButton ( 0 ) ) ;
1104+ const modal = await browser . $ ( Selectors . FocusModeModal ) ;
1105+ await modal . waitForDisplayed ( ) ;
1106+
1107+ await browser . $ ( Selectors . FocusModeStageInput ) . waitForDisplayed ( ) ;
1108+ await browser . $ ( Selectors . FocusModeStageEditor ) . waitForDisplayed ( ) ;
1109+ await browser . $ ( Selectors . FocusModeStageOutput ) . waitForDisplayed ( ) ;
1110+
1111+ const closeButton = await browser . $ ( Selectors . FocusModeCloseModalButton ) ;
1112+ await closeButton . click ( ) ;
1113+
1114+ await modal . waitForDisplayed ( { reverse : true } ) ;
1115+ } ) ;
1116+
1117+ it ( 'navigates between stages' , async function ( ) {
1118+ await browser . selectStageOperator ( 0 , '$match' ) ;
1119+ await browser . setAceValue ( Selectors . stageEditor ( 0 ) , '{ i: 5 }' ) ;
1120+
1121+ await browser . clickVisible ( Selectors . AddStageButton ) ;
1122+ await browser . $ ( Selectors . stageEditor ( 1 ) ) . waitForDisplayed ( ) ;
1123+ await browser . selectStageOperator ( 1 , '$limit' ) ;
1124+ await browser . setAceValue ( Selectors . stageEditor ( 1 ) , '10' ) ;
1125+
1126+ await browser . clickVisible ( Selectors . AddStageButton ) ;
1127+ await browser . $ ( Selectors . stageEditor ( 2 ) ) . waitForDisplayed ( ) ;
1128+ await browser . selectStageOperator ( 2 , '$sort' ) ;
1129+ await browser . setAceValue ( Selectors . stageEditor ( 2 ) , '{ i: -1 }' ) ;
1130+
1131+ await browser . clickVisible ( Selectors . stageFocusModeButton ( 0 ) ) ;
1132+ const modal = await browser . $ ( Selectors . FocusModeModal ) ;
1133+ await modal . waitForDisplayed ( ) ;
1134+
1135+ const nextButton = await browser . $ ( Selectors . FocusModeNextStageButton ) ;
1136+ const previousButton = await browser . $ (
1137+ Selectors . FocusModePreviousStageButton
1138+ ) ;
1139+
1140+ await nextButton . waitForDisplayed ( ) ;
1141+ await previousButton . waitForDisplayed ( ) ;
1142+
1143+ expect ( await previousButton . isEnabled ( ) ) . to . equal ( false ) ;
1144+
1145+ await browser . waitUntil ( async ( ) => {
1146+ const activeStage = await browser . $ (
1147+ Selectors . FocusModeActiveStageLabel
1148+ ) ;
1149+ return ( await activeStage . getText ( ) ) === 'Stage 1: $match' ;
1150+ } ) ;
1151+
1152+ await nextButton . click ( ) ;
1153+ await browser . waitUntil ( async ( ) => {
1154+ const activeStage = await browser . $ (
1155+ Selectors . FocusModeActiveStageLabel
1156+ ) ;
1157+ return ( await activeStage . getText ( ) ) === 'Stage 2: $limit' ;
1158+ } ) ;
1159+
1160+ await nextButton . click ( ) ;
1161+ await browser . waitUntil ( async ( ) => {
1162+ const activeStage = await browser . $ (
1163+ Selectors . FocusModeActiveStageLabel
1164+ ) ;
1165+ return ( await activeStage . getText ( ) ) === 'Stage 3: $sort' ;
1166+ } ) ;
1167+
1168+ expect ( await nextButton . isEnabled ( ) ) . to . equal ( false ) ;
1169+
1170+ await previousButton . click ( ) ;
1171+ await browser . waitUntil ( async ( ) => {
1172+ const activeStage = await browser . $ (
1173+ Selectors . FocusModeActiveStageLabel
1174+ ) ;
1175+ return ( await activeStage . getText ( ) ) === 'Stage 2: $limit' ;
1176+ } ) ;
1177+
1178+ await previousButton . click ( ) ;
1179+ await browser . waitUntil ( async ( ) => {
1180+ const activeStage = await browser . $ (
1181+ Selectors . FocusModeActiveStageLabel
1182+ ) ;
1183+ return ( await activeStage . getText ( ) ) === 'Stage 1: $match' ;
1184+ } ) ;
1185+
1186+ expect ( await previousButton . isEnabled ( ) ) . to . equal ( false ) ;
1187+
1188+ await browser . keys ( 'Escape' ) ;
1189+ await modal . waitForDisplayed ( { reverse : true } ) ;
1190+ } ) ;
1191+
1192+ it ( 'adds a new stage before or after current stage' , async function ( ) {
1193+ await browser . selectStageOperator ( 0 , '$match' ) ;
1194+ await browser . setAceValue ( Selectors . stageEditor ( 0 ) , '{ i: 5 }' ) ;
1195+
1196+ await browser . clickVisible ( Selectors . stageFocusModeButton ( 0 ) ) ;
1197+ const modal = await browser . $ ( Selectors . FocusModeModal ) ;
1198+ await modal . waitForDisplayed ( ) ;
1199+
1200+ await browser . waitUntil ( async ( ) => {
1201+ const activeStage = await browser . $ (
1202+ Selectors . FocusModeActiveStageLabel
1203+ ) ;
1204+ return ( await activeStage . getText ( ) ) === 'Stage 1: $match' ;
1205+ } ) ;
1206+
1207+ const addStageMenu = await browser . $ (
1208+ Selectors . FocusModeAddStageMenuButton
1209+ ) ;
1210+ await addStageMenu . waitForDisplayed ( ) ;
1211+
1212+ // Add a stage before the current stage.
1213+ await addStageMenu . click ( ) ;
1214+
1215+ const addStageBeforeButton = await browser . $ (
1216+ Selectors . FocusModeAddStageBeforeMenuItem
1217+ ) ;
1218+ await addStageBeforeButton . waitForDisplayed ( ) ;
1219+ await addStageBeforeButton . click ( ) ;
1220+
1221+ await browser . waitUntil ( async ( ) => {
1222+ const labelElem = await browser . $ ( Selectors . FocusModeActiveStageLabel ) ;
1223+ return ( await labelElem . getText ( ) ) === 'Stage 1: select' ;
1224+ } ) ;
1225+
1226+ // Add a stage after the current stage.
1227+ await addStageMenu . click ( ) ;
1228+
1229+ const addStageAfterButton = await browser . $ (
1230+ Selectors . FocusModeAddStageAfterMenuItem
1231+ ) ;
1232+ await addStageAfterButton . waitForDisplayed ( ) ;
1233+ await addStageAfterButton . click ( ) ;
1234+
1235+ await browser . waitUntil ( async ( ) => {
1236+ const activeStage = await browser . $ (
1237+ Selectors . FocusModeActiveStageLabel
1238+ ) ;
1239+ return ( await activeStage . getText ( ) ) === 'Stage 2: select' ;
1240+ } ) ;
1241+
1242+ await browser . keys ( 'Escape' ) ;
1243+ await modal . waitForDisplayed ( { reverse : true } ) ;
1244+ } ) ;
1245+
1246+ it ( 'hides stage input and output when preview is disabled' , async function ( ) {
1247+ await browser . clickVisible ( Selectors . AggregationAutoPreviewToggle ) ;
1248+
1249+ await browser . selectStageOperator ( 0 , '$match' ) ;
1250+ await browser . setAceValue ( Selectors . stageEditor ( 0 ) , '{ i: 5 }' ) ;
1251+
1252+ await browser . clickVisible ( Selectors . stageFocusModeButton ( 0 ) ) ;
1253+ const modal = await browser . $ ( Selectors . FocusModeModal ) ;
1254+ await modal . waitForDisplayed ( ) ;
1255+
1256+ await browser
1257+ . $ ( Selectors . FocusModeStageInput )
1258+ . waitForDisplayed ( { reverse : true } ) ;
1259+ await browser . $ ( Selectors . FocusModeStageEditor ) . waitForDisplayed ( ) ;
1260+ await browser
1261+ . $ ( Selectors . FocusModeStageOutput )
1262+ . waitForDisplayed ( { reverse : true } ) ;
1263+ } ) ;
1264+
1265+ it ( 'handles $out stage operators' , async function ( ) {
1266+ await browser . selectStageOperator ( 0 , '$out' ) ;
1267+ await browser . setAceValue ( Selectors . stageEditor ( 0 ) , '"test"' ) ;
1268+
1269+ await browser . clickVisible ( Selectors . stageFocusModeButton ( 0 ) ) ;
1270+ const modal = await browser . $ ( Selectors . FocusModeModal ) ;
1271+ await modal . waitForDisplayed ( ) ;
1272+
1273+ await browser . waitUntil ( async ( ) => {
1274+ const outputElem = await browser . $ ( Selectors . FocusModeStageOutput ) ;
1275+ const text = await outputElem . getText ( ) ;
1276+ return text . includes ( OUT_STAGE_PREVIEW_TEXT ) ;
1277+ } ) ;
1278+ } ) ;
1279+
1280+ it ( 'handles $merge stage operators' , async function ( ) {
1281+ if ( serverSatisfies ( '< 4.2.0' ) ) {
1282+ return this . skip ( ) ;
1283+ }
1284+
1285+ await browser . selectStageOperator ( 0 , '$merge' ) ;
1286+ await browser . setAceValue ( Selectors . stageEditor ( 0 ) , '"test"' ) ;
1287+
1288+ await browser . clickVisible ( Selectors . stageFocusModeButton ( 0 ) ) ;
1289+ const modal = await browser . $ ( Selectors . FocusModeModal ) ;
1290+ await modal . waitForDisplayed ( ) ;
1291+
1292+ await browser . waitUntil ( async ( ) => {
1293+ const outputElem = await browser . $ ( Selectors . FocusModeStageOutput ) ;
1294+ const text = await outputElem . getText ( ) ;
1295+ return text . includes ( MERGE_STAGE_PREVIEW_TEXT ) ;
1296+ } ) ;
1297+ } ) ;
1298+
1299+ it ( 'handles atlas only operator' , async function ( ) {
1300+ if ( serverSatisfies ( '< 4.1.11' ) ) {
1301+ this . skip ( ) ;
1302+ }
1303+
1304+ await browser . selectStageOperator ( 0 , '$search' ) ;
1305+ await browser . setAceValue ( Selectors . stageEditor ( 0 ) , '{}' ) ;
1306+
1307+ await browser . clickVisible ( Selectors . stageFocusModeButton ( 0 ) ) ;
1308+ const modal = await browser . $ ( Selectors . FocusModeModal ) ;
1309+ await modal . waitForDisplayed ( ) ;
1310+
1311+ await browser . waitUntil ( async ( ) => {
1312+ const outputElem = await browser . $ ( Selectors . FocusModeStageOutput ) ;
1313+ const text = await outputElem . getText ( ) ;
1314+ return text . includes (
1315+ 'The $search stage is only available with MongoDB Atlas.'
1316+ ) ;
1317+ } ) ;
1318+ } ) ;
1319+ } ) ;
1320+
10961321 // TODO: stages can be re-arranged by drag and drop and the preview is refreshed after rearranging them
10971322 // TODO: test auto-preview and limit
10981323 // TODO: save a pipeline, close compass, re-open compass, load the pipeline
0 commit comments