{
  "A successful message delays offline status": {
    "describeName": "Offline:",
    "itName": "A successful message delays offline status",
    "tags": [
    ],
    "config": {
      "numClients": 1,
      "useGarbageCollection": true
    },
    "steps": [
      {
        "userListen": [
          2,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedState": {
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      },
      {
        "watchAck": [
          2
        ]
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        }
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        },
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ]
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        }
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        }
      }
    ]
  },
  "Client stays offline during credential change": {
    "describeName": "Offline:",
    "itName": "Client stays offline during credential change",
    "tags": [
    ],
    "config": {
      "numClients": 1,
      "useGarbageCollection": true
    },
    "steps": [
      {
        "enableNetwork": false,
        "expectedState": {
          "activeLimboDocs": [
          ],
          "activeTargets": {
          },
          "enqueuedLimboDocs": [
          ]
        }
      },
      {
        "changeUser": "user1"
      },
      {
        "userListen": [
          2,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ],
        "expectedState": {
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      }
    ]
  },
  "Empty queries are resolved if client goes offline": {
    "describeName": "Offline:",
    "itName": "Empty queries are resolved if client goes offline",
    "tags": [
    ],
    "config": {
      "numClients": 1,
      "useGarbageCollection": true
    },
    "steps": [
      {
        "userListen": [
          2,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedState": {
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        },
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ]
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        }
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        }
      }
    ]
  },
  "New queries return immediately with fromCache=true when offline due to OnlineState timeout.": {
    "describeName": "Offline:",
    "itName": "New queries return immediately with fromCache=true when offline due to OnlineState timeout.",
    "tags": [
    ],
    "config": {
      "numClients": 1,
      "useGarbageCollection": true
    },
    "steps": [
      {
        "userListen": [
          2,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedState": {
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      },
      {
        "runTimer": "online_state_timeout",
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ]
      },
      {
        "userListen": [
          4,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection2"
          }
        ],
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection2"
            }
          }
        ],
        "expectedState": {
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            },
            "4": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection2"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      }
    ]
  },
  "New queries return immediately with fromCache=true when offline due to stream failures.": {
    "describeName": "Offline:",
    "itName": "New queries return immediately with fromCache=true when offline due to stream failures.",
    "tags": [
    ],
    "config": {
      "numClients": 1,
      "useGarbageCollection": true
    },
    "steps": [
      {
        "userListen": [
          2,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedState": {
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        },
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ]
      },
      {
        "userListen": [
          4,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection2"
          }
        ],
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection2"
            }
          }
        ],
        "expectedState": {
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            },
            "4": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection2"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      }
    ]
  },
  "OnlineState timeout triggers offline behavior": {
    "describeName": "Offline:",
    "itName": "OnlineState timeout triggers offline behavior",
    "tags": [
    ],
    "config": {
      "numClients": 1,
      "useGarbageCollection": true
    },
    "steps": [
      {
        "userListen": [
          2,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedState": {
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      },
      {
        "runTimer": "online_state_timeout",
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ]
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        }
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        }
      },
      {
        "watchAck": [
          2
        ]
      },
      {
        "watchEntity": {
          "docs": [
            {
              "key": "collection/a",
              "options": {
                "hasCommittedMutations": false,
                "hasLocalMutations": false
              },
              "value": {
                "key": "a"
              },
              "version": 1000
            }
          ],
          "targets": [
            2
          ]
        }
      },
      {
        "watchCurrent": [
          [
            2
          ],
          "resume-token-1000"
        ]
      },
      {
        "watchSnapshot": {
          "targetIds": [
          ],
          "version": 1000
        },
        "expectedSnapshotEvents": [
          {
            "added": [
              {
                "key": "collection/a",
                "options": {
                  "hasCommittedMutations": false,
                  "hasLocalMutations": false
                },
                "value": {
                  "key": "a"
                },
                "version": 1000
              }
            ],
            "errorCode": 0,
            "fromCache": false,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ]
      },
      {
        "runTimer": "all"
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        },
        "expectedState": {
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": "resume-token-1000"
            }
          }
        }
      },
      {
        "runTimer": "online_state_timeout",
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ]
      }
    ]
  },
  "Queries return from cache when network disabled": {
    "describeName": "Offline:",
    "itName": "Queries return from cache when network disabled",
    "tags": [
      "eager-gc"
    ],
    "config": {
      "numClients": 1,
      "useGarbageCollection": true
    },
    "steps": [
      {
        "enableNetwork": false,
        "expectedState": {
          "activeLimboDocs": [
          ],
          "activeTargets": {
          },
          "enqueuedLimboDocs": [
          ]
        }
      },
      {
        "userListen": [
          2,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ],
        "expectedState": {
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      },
      {
        "userUnlisten": [
          2,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedState": {
          "activeTargets": {
          }
        }
      },
      {
        "userListen": [
          4,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ],
        "expectedState": {
          "activeTargets": {
            "4": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      },
      {
        "userUnlisten": [
          4,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedState": {
          "activeTargets": {
          }
        }
      }
    ]
  },
  "Queries revert to fromCache=true when offline.": {
    "describeName": "Offline:",
    "itName": "Queries revert to fromCache=true when offline.",
    "tags": [
    ],
    "config": {
      "numClients": 1,
      "useGarbageCollection": true
    },
    "steps": [
      {
        "userListen": [
          2,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedState": {
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      },
      {
        "watchAck": [
          2
        ]
      },
      {
        "watchEntity": {
          "docs": [
            {
              "key": "collection/a",
              "options": {
                "hasCommittedMutations": false,
                "hasLocalMutations": false
              },
              "value": {
                "key": "a"
              },
              "version": 1000
            }
          ],
          "targets": [
            2
          ]
        }
      },
      {
        "watchCurrent": [
          [
            2
          ],
          "resume-token-1000"
        ]
      },
      {
        "watchSnapshot": {
          "targetIds": [
          ],
          "version": 1000
        },
        "expectedSnapshotEvents": [
          {
            "added": [
              {
                "key": "collection/a",
                "options": {
                  "hasCommittedMutations": false,
                  "hasLocalMutations": false
                },
                "value": {
                  "key": "a"
                },
                "version": 1000
              }
            ],
            "errorCode": 0,
            "fromCache": false,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ]
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        },
        "expectedState": {
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": "resume-token-1000"
            }
          }
        }
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        },
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ]
      },
      {
        "watchAck": [
          2
        ]
      },
      {
        "watchEntity": {
          "docs": [
          ],
          "targets": [
            2
          ]
        }
      },
      {
        "watchCurrent": [
          [
            2
          ],
          "resume-token-1000"
        ]
      },
      {
        "watchSnapshot": {
          "targetIds": [
          ],
          "version": 1000
        },
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": false,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ]
      }
    ]
  },
  "Queries with limbo documents handle going offline.": {
    "describeName": "Offline:",
    "itName": "Queries with limbo documents handle going offline.",
    "tags": [
    ],
    "config": {
      "numClients": 1,
      "useGarbageCollection": true
    },
    "steps": [
      {
        "userListen": [
          2,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedState": {
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      },
      {
        "watchAck": [
          2
        ]
      },
      {
        "watchEntity": {
          "docs": [
            {
              "key": "collection/a",
              "options": {
                "hasCommittedMutations": false,
                "hasLocalMutations": false
              },
              "value": {
                "key": "a"
              },
              "version": 1000
            }
          ],
          "targets": [
            2
          ]
        }
      },
      {
        "watchCurrent": [
          [
            2
          ],
          "resume-token-1000"
        ]
      },
      {
        "watchSnapshot": {
          "targetIds": [
          ],
          "version": 1000
        },
        "expectedSnapshotEvents": [
          {
            "added": [
              {
                "key": "collection/a",
                "options": {
                  "hasCommittedMutations": false,
                  "hasLocalMutations": false
                },
                "value": {
                  "key": "a"
                },
                "version": 1000
              }
            ],
            "errorCode": 0,
            "fromCache": false,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ]
      },
      {
        "watchReset": [
          2
        ]
      },
      {
        "watchCurrent": [
          [
            2
          ],
          "resume-token-1001"
        ]
      },
      {
        "watchSnapshot": {
          "targetIds": [
          ],
          "version": 1001
        },
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ],
        "expectedState": {
          "activeLimboDocs": [
            "collection/a"
          ],
          "activeTargets": {
            "1": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection/a"
                }
              ],
              "resumeToken": ""
            },
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        },
        "expectedState": {
          "activeTargets": {
            "1": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection/a"
                }
              ],
              "resumeToken": ""
            },
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": "resume-token-1001"
            }
          }
        }
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        }
      },
      {
        "watchAck": [
          2
        ]
      },
      {
        "watchEntity": {
          "docs": [
          ],
          "targets": [
            2
          ]
        }
      },
      {
        "watchCurrent": [
          [
            2
          ],
          "resume-token-1001"
        ]
      },
      {
        "watchSnapshot": {
          "targetIds": [
          ],
          "version": 1001
        }
      },
      {
        "watchAck": [
          1
        ]
      },
      {
        "watchEntity": {
          "docs": [
          ],
          "targets": [
            1
          ]
        }
      },
      {
        "watchCurrent": [
          [
            1
          ],
          "resume-token-1001"
        ]
      },
      {
        "watchSnapshot": {
          "targetIds": [
          ],
          "version": 1001
        },
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": false,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            },
            "removed": [
              {
                "key": "collection/a",
                "options": {
                  "hasCommittedMutations": false,
                  "hasLocalMutations": false
                },
                "value": {
                  "key": "a"
                },
                "version": 1000
              }
            ]
          }
        ],
        "expectedState": {
          "activeLimboDocs": [
          ],
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": "resume-token-1001"
            }
          }
        }
      }
    ]
  },
  "Removing all listeners delays \"Offline\" status on next listen": {
    "comment": "Marked as no-lru because when a listen is re-added, it gets a new target id rather than reusing one",
    "describeName": "Offline:",
    "itName": "Removing all listeners delays \"Offline\" status on next listen",
    "tags": [
      "eager-gc"
    ],
    "config": {
      "numClients": 1,
      "useGarbageCollection": true
    },
    "steps": [
      {
        "userListen": [
          2,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedState": {
          "activeTargets": {
            "2": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        },
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ]
      },
      {
        "userUnlisten": [
          2,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedState": {
          "activeTargets": {
          }
        }
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        }
      },
      {
        "userListen": [
          4,
          {
            "filters": [
            ],
            "orderBys": [
            ],
            "path": "collection"
          }
        ],
        "expectedState": {
          "activeTargets": {
            "4": {
              "queries": [
                {
                  "filters": [
                  ],
                  "orderBys": [
                  ],
                  "path": "collection"
                }
              ],
              "resumeToken": ""
            }
          }
        }
      },
      {
        "watchStreamClose": {
          "error": {
            "code": 14,
            "message": "Simulated Backend Error"
          },
          "runBackoffTimer": true
        },
        "expectedSnapshotEvents": [
          {
            "errorCode": 0,
            "fromCache": true,
            "hasPendingWrites": false,
            "query": {
              "filters": [
              ],
              "orderBys": [
              ],
              "path": "collection"
            }
          }
        ]
      }
    ]
  }
}
