diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml new file mode 100644 index 00000000..12943d0a --- /dev/null +++ b/.github/workflows/unit-test.yml @@ -0,0 +1,38 @@ +name: Unit Tests + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + unit-test: + runs-on: ubuntu-latest + steps: + - name: Get Repo + uses: actions/checkout@v3 + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'npm' + - name: Install Dependencies + run: npm ci + - name: Run Tests + run: npm test + + build: + runs-on: ubuntu-latest + steps: + - name: Get Repo + uses: actions/checkout@v3 + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: 'npm' + - name: Install Dependencies + run: npm ci + - name: Build Project + run: npm run build diff --git a/package.json b/package.json index 33f18883..c2b81327 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "test:all": "vitest", "test:accessibility": "vitest accessibility --run", "coverage": "vitest --coverage --run", - "test": "echo \"Navigate into an example and run the tests from there!\" && exit 1", + "test": "vitest", "build": "tsc && vite build", "preview": "vite preview" }, diff --git a/src/examples/great-expectations/exercise.test.ts b/src/examples/great-expectations/exercise.test.ts index 0bf7ad95..2b208ed8 100644 --- a/src/examples/great-expectations/exercise.test.ts +++ b/src/examples/great-expectations/exercise.test.ts @@ -12,144 +12,133 @@ import { KanbanBoard } from '$lib/kanban-board'; * toThrowError: https://vitest.dev/api/expect.html#tothrowerror */ -it.todo( - 'should pass if the two numbers would add up correctly in a language other than JavaScript', - () => { - expect(0.2 + 0.1).toEqual(0.3); - }, -); +it('should pass if the two numbers would add up correctly in a language other than JavaScript', () => { + expect(0.2 + 0.1).toBeCloseTo(0.3); +}); describe('createPerson', () => { - it.todo('should create an instance of a person', () => { + it('should create an instance of a person', () => { const person = createPerson('Ada Lovelace'); expect.hasAssertions(); - // Verify that person is an instance of a Person. + expect(person).toBeInstanceOf(Person); }); }); describe('Kanban Board', () => { - it.todo('should include "Backlog" in board.statuses', () => { + it('should include "Backlog" in board.statuses', () => { const board = new KanbanBoard('Things to Do'); expect.hasAssertions(); - // Verify that board.statuses contains "Backlog". + expect(board.statuses).toContain('Backlog'); }); - it.todo('should *not* include "Bogus" in board.statuses', () => { + it('should *not* include "Bogus" in board.statuses', () => { const board = new KanbanBoard('Things to Do'); expect.hasAssertions(); - // Verify that board.statuses does not contain "Bogus". + expect(board.statuses).not.toContain('Bogus'); }); - it.todo( - 'should include an added status in board.statuses using #addStatus', - () => { - const board = new KanbanBoard('Things to Do'); - expect.hasAssertions(); - // Use board.addStatus to add a status. - // Verify that the new status is—in fact—now in board.statuses. - }, - ); - - it.todo('should remove a status using #removeStatus', () => { + it('should include an added status in board.statuses using #addStatus', () => { const board = new KanbanBoard('Things to Do'); expect.hasAssertions(); - // Use board.removeStatus to remove a status. - - // You can be clever or you can just assume "Backlog" is in board.statuses - // by default. + const newStatus = 'Testing'; + board.addStatus(newStatus); + expect(board.statuses).toContain(newStatus); + }); - // Verify that the status is no longer in in board.statuses. + it('should remove a status using #removeStatus', () => { + const board = new KanbanBoard('Things to Do'); + expect.hasAssertions(); + const statusToRemove = 'Ready'; + expect(board.statuses).toContain(statusToRemove); + board.removeStatus(statusToRemove); + expect(board.statuses).not.toContain(statusToRemove); }); }); describe('Person', () => { - it.todo('will create a person with a first name', () => { + it('will create a person with a first name', () => { const person = new Person('Madonna'); expect.hasAssertions(); - // Verify that person.firstName is correct. + expect(person).toHaveProperty('firstName', 'Madonna'); }); - it.todo('will create a person with a first and last name', () => { + it('will create a person with a first and last name', () => { const person = new Person('Madonna Cicone'); expect.hasAssertions(); - // Verify that person.lastName is correct. + expect(person).toHaveProperty('firstName', 'Madonna'); + expect(person).toHaveProperty('lastName', 'Cicone'); }); - it.todo('will create a person with a first, middle, and last name', () => { + it('will create a person with a first, middle, and last name', () => { const person = new Person('Madonna Louise Cicone'); expect.hasAssertions(); - // Verify that person.middleName is correct. + expect(person).toHaveProperty('firstName', 'Madonna'); + expect(person).toHaveProperty('middleName', 'Louise'); + expect(person).toHaveProperty('lastName', 'Cicone'); }); - it.todo('will throw if you provide an empty string', () => { + it('will throw if you provide an empty string', () => { const fn = () => { new Person(''); }; expect.hasAssertions(); - - // Verify that function above throws. + expect(fn).toThrowError(); }); - it.todo( - 'will throw a specific error message if you provide an empty string', - () => { - const errorMessage = 'fullName cannot be an empty string'; + it('will throw a specific error message if you provide an empty string', () => { + const errorMessage = 'fullName cannot be an empty string'; - const fn = () => { - new Person(''); - }; - - expect.hasAssertions(); + const fn = () => { + new Person(''); + }; - // Verify that function above throws the error message above. - }, - ); + expect.hasAssertions(); + expect(fn).toThrowError(errorMessage); + }); - it.todo('will add a friend', () => { + it('will add a friend', () => { const john = new Person('John Lennon'); const paul = new Person('Paul McCartney'); john.addFriend(paul); expect.hasAssertions(); - - // Verify that john.friends contains paul. + expect(john.friends).toContain(paul); }); - it.todo('will mutually add a friend', () => { + it('will mutually add a friend', () => { const john = new Person('John Lennon'); const paul = new Person('Paul McCartney'); john.addFriend(paul); expect.hasAssertions(); - - // Verify that paul.friends contains john. + expect(paul.friends).toContain(john); }); - it.todo('will remove a friend', () => { + it('will remove a friend', () => { const john = new Person('John Lennon'); const paul = new Person('Paul McCartney'); john.addFriend(paul); + expect(john.friends).toContain(paul); john.removeFriend(paul); expect.hasAssertions(); - - // Verify that john.friends does not include paul. + expect(john.friends).not.toContain(paul); }); - it.todo('will mutually remove friends', () => { + it('will mutually remove friends', () => { const john = new Person('John Lennon'); const paul = new Person('Paul McCartney'); john.addFriend(paul); + expect(paul.friends).toContain(john); john.removeFriend(paul); expect.hasAssertions(); - - // Verify that paul.friends does not include john. + expect(paul.friends).not.toContain(john); }); }); @@ -158,11 +147,13 @@ const explode = () => { }; describe('explode', () => { - it.todo('should throw an error', () => { - explode(); + it('should throw an error', () => { + const fn = () => explode(); + expect(fn).toThrowError(); }); - it.todo('should throw a specific error containing "terribly wrong"', () => { - explode(); + it('should throw a specific error containing "terribly wrong"', () => { + const fn = () => explode(); + expect(fn).toThrowError(/terribly wrong/i); }); }); diff --git a/src/examples/great-expectations/items-slice.test.ts b/src/examples/great-expectations/items-slice.test.ts index 4a9bebee..67f52e86 100644 --- a/src/examples/great-expectations/items-slice.test.ts +++ b/src/examples/great-expectations/items-slice.test.ts @@ -10,22 +10,28 @@ it('returns an empty array as the initial state', () => { expect(reducer(undefined, { type: 'noop' })).toEqual([]); }); -it.todo('supports adding an item with the correct name', () => { +it('supports adding an item with the correct name', () => { expect.hasAssertions(); - const result = reducer([], add({ name: 'iPhone' })); + const itemName = 'iPhone'; + const result = reducer([], add({ name: itemName })); + expect(result).toEqual([expect.objectContaining({ name: itemName })]); }); -it.todo('prefixes ids with "item-"', () => { +it('prefixes ids with "item-"', () => { expect.hasAssertions(); const result = reducer([], add({ name: 'iPhone' })); + expect(result).toEqual([ + expect.objectContaining({ id: expect.stringMatching(/^item-/) }), + ]); }); -it.todo('defaults new items to a packed status of false', () => { +it('defaults new items to a packed status of false', () => { expect.hasAssertions(); const result = reducer([], add({ name: 'iPhone' })); + expect(result).toEqual([expect.objectContaining({ packed: false })]); }); -it.todo('supports removing an item', () => { +it('supports removing an item', () => { expect.hasAssertions(); const state = [ { @@ -36,9 +42,10 @@ it.todo('supports removing an item', () => { ]; const result = reducer(state, remove({ id: '1' })); + expect(result).not.toContain(expect.objectContaining({ id: '1' })); }); -it.todo('supports toggling an item', () => { +it('supports toggling an item', () => { expect.hasAssertions(); const state = [ { @@ -49,9 +56,12 @@ it.todo('supports toggling an item', () => { ]; const result = reducer(state, toggle({ id: '1' })); + expect(result).not.toEqual( + expect.objectContaining({ packed: state[0].packed }), + ); }); -it.todo('supports updating an item', () => { +it('supports updating an item', () => { expect.hasAssertions(); const state = [ { @@ -65,9 +75,13 @@ it.todo('supports updating an item', () => { state, update({ id: '1', name: 'Samsung Galaxy S23' }), ); + expect(result).not.toEqual([expect.objectContaining({ name: 'iPhone' })]); + expect(result).toEqual([ + expect.objectContaining({ name: 'Samsung Galaxy S23' }), + ]); }); -it.todo('supports marking all items as unpacked', () => { +it('supports marking all items as unpacked', () => { expect.hasAssertions(); const state = [ { @@ -83,4 +97,5 @@ it.todo('supports marking all items as unpacked', () => { ]; const result = reducer(state, markAllAsUnpacked()); + expect(result).toMatchObject([{ packed: false }, { packed: false }]); });