@@ -1074,3 +1074,296 @@ test('aroundAll enforces teardown timeout when inner error is caught', async ()
10741074 }
10751075 ` )
10761076} )
1077+
1078+ function extractLogs ( log : string ) {
1079+ const result = log . split ( '\n' ) . filter ( line => line . match ( / ^ ! [ < > ] / ) ) . join ( '\n' )
1080+ return `\n${ result . trim ( ) } \n`
1081+ }
1082+
1083+ test ( 'sibling task sequential lifecycle guarantee' , async ( ) => {
1084+ const result = await runInlineTests ( {
1085+ 'basic.test.ts' : `
1086+ const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
1087+
1088+ beforeEach(async ({ task }) => {
1089+ console.log("!> beforeEach", task.name)
1090+ await sleep(10)
1091+ console.log("!< beforeEach", task.name)
1092+ })
1093+
1094+ afterEach(async ({ task }) => {
1095+ console.log("!> afterEach", task.name)
1096+ await sleep(10)
1097+ console.log("!< afterEach", task.name)
1098+ })
1099+
1100+ test.concurrent.for(["a", "b"])("%s", async (_, { task }) => {
1101+ console.log("!> test", task.name)
1102+ await sleep(10)
1103+ console.log("!< test", task.name)
1104+ })
1105+ ` ,
1106+ } , {
1107+ maxConcurrency : 1 ,
1108+ globals : true ,
1109+ } )
1110+
1111+ expect ( extractLogs ( result . stdout ) ) . toMatchInlineSnapshot ( `
1112+ "
1113+ !> beforeEach a
1114+ !< beforeEach a
1115+ !> test a
1116+ !< test a
1117+ !> afterEach a
1118+ !< afterEach a
1119+ !> beforeEach b
1120+ !< beforeEach b
1121+ !> test b
1122+ !< test b
1123+ !> afterEach b
1124+ !< afterEach b
1125+ "
1126+ ` )
1127+ expect ( result . errorTree ( ) ) . toMatchInlineSnapshot ( `
1128+ {
1129+ "basic.test.ts": {
1130+ "a": "passed",
1131+ "b": "passed",
1132+ },
1133+ }
1134+ ` )
1135+ } )
1136+
1137+ test ( 'sibling suite sequential lifecycle guarantee' , async ( ) => {
1138+ const result = await runInlineTests ( {
1139+ 'basic.test.ts' : `
1140+ const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
1141+
1142+ describe.for(["a", "b"])("%s", { concurrent: true }, () => {
1143+ beforeAll(async ({}, suite) => {
1144+ console.log("!> beforeAll", suite.name)
1145+ await sleep(10)
1146+ console.log("!< beforeAll", suite.name)
1147+ })
1148+
1149+ afterAll(async ({}, suite) => {
1150+ console.log("!> afterAll", suite.name)
1151+ await sleep(10)
1152+ console.log("!< afterAll", suite.name)
1153+ })
1154+
1155+ test.concurrent("test", async ({ task }) => {
1156+ console.log("!> test", task.suite.name)
1157+ await sleep(10)
1158+ console.log("!< test", task.suite.name)
1159+ })
1160+ })
1161+ ` ,
1162+ } , {
1163+ maxConcurrency : 1 ,
1164+ globals : true ,
1165+ } )
1166+
1167+ expect ( extractLogs ( result . stdout ) ) . toMatchInlineSnapshot ( `
1168+ "
1169+ !> beforeAll a
1170+ !< beforeAll a
1171+ !> test a
1172+ !< test a
1173+ !> afterAll a
1174+ !< afterAll a
1175+ !> beforeAll b
1176+ !< beforeAll b
1177+ !> test b
1178+ !< test b
1179+ !> afterAll b
1180+ !< afterAll b
1181+ "
1182+ ` )
1183+ expect ( result . errorTree ( ) ) . toMatchInlineSnapshot ( `
1184+ {
1185+ "basic.test.ts": {
1186+ "a": {
1187+ "test": "passed",
1188+ },
1189+ "b": {
1190+ "test": "passed",
1191+ },
1192+ },
1193+ }
1194+ ` )
1195+ } )
1196+
1197+ // we could enforce this by adding yet another limit globally at `runTest`
1198+ // (like we originally had before https://github.com/vitest-dev/vitest/pull/9653)
1199+ // but there's no way to achieve the same for deep suite-level hooks anyways,
1200+ // so we don't do that (yet).
1201+ test ( 'non-sibling test sequential lifecycle non-guarantee' , async ( ) => {
1202+ const result = await runInlineTests ( {
1203+ 'basic.test.ts' : `
1204+ const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
1205+
1206+ describe.for(["a0", "a1"])("%s", { concurrent: true }, () => {
1207+ describe.for(["b0", "b1"])("%s", { concurrent: true }, () => {
1208+ beforeEach(async ({ task }) => {
1209+ console.log("!> beforeEach", task.suite.suite.name, task.suite.name, task.name)
1210+ await sleep(10)
1211+ console.log("!< beforeEach", task.suite.suite.name, task.suite.name, task.name)
1212+ })
1213+
1214+ afterEach(async ({ task }) => {
1215+ console.log("!> afterEach", task.suite.suite.name, task.suite.name, task.name)
1216+ await sleep(10)
1217+ console.log("!< afterEach", task.suite.suite.name, task.suite.name, task.name)
1218+ })
1219+
1220+ test("test", async ({ task }) => {
1221+ console.log("!> test", task.suite.suite.name,task.suite.name, task.name)
1222+ await sleep(10)
1223+ console.log("!< test", task.suite.suite.name,task.suite.name, task.name)
1224+ })
1225+ })
1226+ })
1227+ ` ,
1228+ } , {
1229+ maxConcurrency : 2 ,
1230+ globals : true ,
1231+ } )
1232+
1233+ expect ( extractLogs ( result . stdout ) ) . toMatchInlineSnapshot ( `
1234+ "
1235+ !> beforeEach a0 b0 test
1236+ !> beforeEach a0 b1 test
1237+ !< beforeEach a0 b0 test
1238+ !> beforeEach a1 b0 test
1239+ !< beforeEach a0 b1 test
1240+ !> beforeEach a1 b1 test
1241+ !< beforeEach a1 b0 test
1242+ !> test a0 b0 test
1243+ !< beforeEach a1 b1 test
1244+ !> test a0 b1 test
1245+ !< test a0 b0 test
1246+ !> test a1 b0 test
1247+ !< test a0 b1 test
1248+ !> test a1 b1 test
1249+ !< test a1 b0 test
1250+ !> afterEach a0 b0 test
1251+ !< test a1 b1 test
1252+ !> afterEach a0 b1 test
1253+ !< afterEach a0 b0 test
1254+ !> afterEach a1 b0 test
1255+ !< afterEach a0 b1 test
1256+ !> afterEach a1 b1 test
1257+ !< afterEach a1 b0 test
1258+ !< afterEach a1 b1 test
1259+ "
1260+ ` )
1261+
1262+ expect ( result . errorTree ( ) ) . toMatchInlineSnapshot ( `
1263+ {
1264+ "basic.test.ts": {
1265+ "a0": {
1266+ "b0": {
1267+ "test": "passed",
1268+ },
1269+ "b1": {
1270+ "test": "passed",
1271+ },
1272+ },
1273+ "a1": {
1274+ "b0": {
1275+ "test": "passed",
1276+ },
1277+ "b1": {
1278+ "test": "passed",
1279+ },
1280+ },
1281+ },
1282+ }
1283+ ` )
1284+ } )
1285+
1286+ test ( 'non-sibling suite sequential lifecycle non-guarantee' , async ( ) => {
1287+ const result = await runInlineTests ( {
1288+ 'basic.test.ts' : `
1289+ const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
1290+
1291+ describe.for(["a0", "a1"])("%s", { concurrent: true }, () => {
1292+ describe.for(["b0", "b1"])("%s", { concurrent: true }, () => {
1293+ beforeAll(async ({}, suite) => {
1294+ console.log("!> beforeAll", suite.suite.name, suite.name)
1295+ await sleep(10)
1296+ console.log("!< beforeAll", suite.suite.name, suite.name)
1297+ })
1298+
1299+ afterAll(async ({}, suite) => {
1300+ console.log("!> afterAll", suite.suite.name, suite.name)
1301+ await sleep(10)
1302+ console.log("!< afterAll", suite.suite.name, suite.name)
1303+ })
1304+
1305+ test("test", async ({ task }) => {
1306+ console.log("!> test", task.suite.suite.name, task.suite.name, task.name)
1307+ await sleep(10)
1308+ console.log("!< test", task.suite.suite.name, task.suite.name, task.name)
1309+ })
1310+ })
1311+ })
1312+ ` ,
1313+ } , {
1314+ maxConcurrency : 2 ,
1315+ globals : true ,
1316+ } )
1317+
1318+ expect ( extractLogs ( result . stdout ) ) . toMatchInlineSnapshot ( `
1319+ "
1320+ !> beforeAll a0 b0
1321+ !> beforeAll a0 b1
1322+ !< beforeAll a0 b0
1323+ !> beforeAll a1 b0
1324+ !< beforeAll a0 b1
1325+ !> beforeAll a1 b1
1326+ !< beforeAll a1 b0
1327+ !> test a0 b0 test
1328+ !< beforeAll a1 b1
1329+ !> test a0 b1 test
1330+ !< test a0 b0 test
1331+ !> test a1 b0 test
1332+ !< test a0 b1 test
1333+ !> test a1 b1 test
1334+ !< test a1 b0 test
1335+ !> afterAll a0 b0
1336+ !< test a1 b1 test
1337+ !> afterAll a0 b1
1338+ !< afterAll a0 b0
1339+ !> afterAll a1 b0
1340+ !< afterAll a0 b1
1341+ !> afterAll a1 b1
1342+ !< afterAll a1 b0
1343+ !< afterAll a1 b1
1344+ "
1345+ ` )
1346+
1347+ expect ( result . errorTree ( ) ) . toMatchInlineSnapshot ( `
1348+ {
1349+ "basic.test.ts": {
1350+ "a0": {
1351+ "b0": {
1352+ "test": "passed",
1353+ },
1354+ "b1": {
1355+ "test": "passed",
1356+ },
1357+ },
1358+ "a1": {
1359+ "b0": {
1360+ "test": "passed",
1361+ },
1362+ "b1": {
1363+ "test": "passed",
1364+ },
1365+ },
1366+ },
1367+ }
1368+ ` )
1369+ } )
0 commit comments