Advent of PBT 2021 - Day 14 - Solution
Tags: challenge, testing, webdev, javascript
Published: 2021-12-14 07:53:16

---
title: Advent of PBT 2021 - Day 14 - Solution
published: true
description: Advent of Property Based Testing 2021 - Day 14 - Solution
tags: challenge,testing,webdev,javascript
//cover_image: https://direct_url_to_image.jpg
---

Our algorithm was: **reorderTabs**.
[Go to the subject itself for more details](https://dev.to/dubzzz/advent-of-pbt-2021-day-14-330h)

CodeSandbox with a possible set of properties you may have come with: https://codesandbox.io/s/advent-of-pbt-day-14-solution-ng2b?file=/src/index.spec.ts&previewwindow=tests

---

For this algorithm I chose to generate the entries requested by the algorithm and not try to build them from intermediate inputs. In other words, I will re-use the same arbitrary in all the properties and check whether or not the algorithm does what it says as checking it did it is simpler than doing it.

The arbitrary we will re-use over and over for this algorithm is:
```ts
function tabsWithSelectionArb() {
  return fc
    .set(fc.nat(), { minLength: 2 })
    .chain((tabs) =>
      fc.record({
        tabs: fc.constant(tabs),
        selectedTabs: fc.subarray(tabs, {
          minLength: 1,
          maxLength: tabs.length - 1
        })
      })
    )
    .chain(({ tabs, selectedTabs }) =>
      fc.record({
        tabs: fc.constant(tabs),
        selectedTabs: fc.constant(selectedTabs),
        movePosition: fc.constantFrom(
          ...tabs.filter((t) => !selectedTabs.includes(t))
        )
      })
    );
}
```

It just computes three valid and mutually compatible values for `tabs`, `selectedTabs` and `movePosition`.

Now we have it, let's see which properties we could create thanks to it.

---

## Property 1: should group selected tabs together

> for any constraints
> it should move the selected tabs close to each others
> in other words we should not have any other tabs between them after the move

Written with fast-check:

```ts
it("should group selected tabs together", () => {
  fc.assert(
    fc.property(
      tabsWithSelectionArb(),
      ({ tabs, selectedTabs, movePosition }) => {
        // Arrange / Act
        const newTabs = reorderTabs(tabs, selectedTabs, movePosition);

        // Assert
        const startMovedSelection = newTabs.indexOf(selectedTabs[0]);
        expect(
          newTabs.slice(
            startMovedSelection,
            startMovedSelection + selectedTabs.length
          )
        ).toEqual(selectedTabs);
      }
    )
  );
});
```

---

## Property 2: should insert all the selected tabs before the move position

> for any constraints
> it should move all the selected tabs before the requested position

Written with fast-check:

```ts
it("should insert all the selected tabs before the move position", () => {
  fc.assert(
    fc.property(
      tabsWithSelectionArb(),
      ({ tabs, selectedTabs, movePosition }) => {
        // Arrange / Act
        const newTabs = reorderTabs(tabs, selectedTabs, movePosition);

        // Assert
        const movePositionIndex = newTabs.indexOf(movePosition);
        for (const selected of selectedTabs) {
          const selectedIndex = newTabs.indexOf(selected);
          expect(selectedIndex).toBeLessThan(movePositionIndex);
        }
      }
    )
  );
});
```

---

## Property 3: should not alter non-selected tabs

> for any constraints
> it should not impact other tabs (non selected ones)

Written with fast-check:

```ts
it("should not alter non-selected tabs", () => {
  fc.assert(
    fc.property(
      tabsWithSelectionArb(),
      ({ tabs, selectedTabs, movePosition }) => {
        // Arrange / Act
        const newTabs = reorderTabs(tabs, selectedTabs, movePosition);

        // Assert
        expect(newTabs.filter((t) => !selectedTabs.includes(t))).toEqual(
          tabs.filter((t) => !selectedTabs.includes(t))
        );
      }
    )
  );
});
```

---

## Property 4: should not change the list of tabs, just its order

> for any constraints
> it should not change the list of tabs but just re-order them

Written with fast-check:

```ts
it("should not change the list of tabs, just its order", () => {
  fc.assert(
    fc.property(
      tabsWithSelectionArb(),
      ({ tabs, selectedTabs, movePosition }) => {
        // Arrange / Act
        const newTabs = reorderTabs(tabs, selectedTabs, movePosition);

        // Assert
        expect([...newTabs].sort()).toEqual([...tabs].sort());
      }
    )
  );
});
```

---

[Back to "Advent of PBT 2021"](https://dev.to/dubzzz/advent-of-pbt-2021-13ee) to see topics covered during the other days and their solutions.

More about this serie on [@ndubien](https://twitter.com/ndubien) or with the hashtag [#AdventOfPBT](https://twitter.com/search?q=%23AdventOfPBT).