diff --git a/ui/src/Components/Grid/AlertGrid/index.test.js b/ui/src/Components/Grid/AlertGrid/index.test.js
new file mode 100644
index 000000000..4f3f7f3e6
--- /dev/null
+++ b/ui/src/Components/Grid/AlertGrid/index.test.js
@@ -0,0 +1,98 @@
+import React from "react";
+
+import { shallow } from "enzyme";
+
+import { MockAlert, MockAlertGroup } from "__mocks__/Alerts.js";
+import { AlertStore } from "Stores/AlertStore";
+import { Settings } from "Stores/Settings";
+import { SilenceFormStore } from "Stores/SilenceFormStore";
+import { AlertGrid } from ".";
+
+let alertStore;
+let settingsStore;
+let silenceFormStore;
+
+beforeEach(() => {
+ alertStore = new AlertStore([]);
+ settingsStore = new Settings();
+ silenceFormStore = new SilenceFormStore();
+});
+
+const ShallowAlertGrid = () => {
+ return shallow(
+
+ );
+};
+
+const MockGroup = (groupName, alertCount) => {
+ let alerts = [];
+ for (let i = 1; i <= alertCount; i++) {
+ alerts.push(MockAlert([], { instance: `instance${i}` }));
+ }
+ const group = MockAlertGroup(
+ { alertname: "Fake Alert", group: groupName },
+ alerts,
+ [],
+ {}
+ );
+ return group;
+};
+
+const MockGroupList = count => {
+ let groups = {};
+ for (let i = 1; i <= count; i++) {
+ let id = `id${i}`;
+ let hash = `hash${i}`;
+ let group = MockGroup(`group${i}`, count);
+ group.id = id;
+ group.hash = hash;
+ groups[id] = group;
+ }
+ alertStore.data.upstreams = {
+ counters: { total: 0, healthy: 1, failed: 0 },
+ instances: [{ name: "am", uri: "http://am", error: "" }]
+ };
+ alertStore.data.groups = groups;
+};
+
+describe("", () => {
+ it("renders only first 50 alert groups", () => {
+ MockGroupList(60);
+ const tree = ShallowAlertGrid();
+ const alertGroups = tree.find("AlertGroup");
+ expect(alertGroups).toHaveLength(50);
+ });
+
+ it("appends 30 groups after loadMore() call", () => {
+ MockGroupList(100);
+ const tree = ShallowAlertGrid();
+ // call it directly, it should happen on scroll to the bottom of the page
+ tree.instance().loadMore();
+ const alertGroups = tree.find("AlertGroup");
+ expect(alertGroups).toHaveLength(80);
+ });
+
+ it("calls masonryRepack() after update`", () => {
+ const tree = ShallowAlertGrid();
+ const instance = tree.instance();
+ const repackSpy = jest.spyOn(instance, "masonryRepack");
+ // it's a shallow render so we don't really have masonry mounted, fake it
+ instance.masonryComponentReference.ref = {
+ forcePack: jest.fn()
+ };
+ instance.componentDidUpdate();
+ expect(repackSpy).toHaveBeenCalled();
+ expect(instance.masonryComponentReference.ref.forcePack).toHaveBeenCalled();
+ });
+
+ it("calling storeMasonryRef() saves the ref in local store", () => {
+ const tree = ShallowAlertGrid();
+ const instance = tree.instance();
+ instance.storeMasonryRef("foo");
+ expect(instance.masonryComponentReference.ref).toBe("foo");
+ });
+});