Skip to content

Commit 5f5c7b9

Browse files
committed
update tests
1 parent 07fdd01 commit 5f5c7b9

File tree

3 files changed

+135
-80
lines changed

3 files changed

+135
-80
lines changed

tests/fixtures/app.ts

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,72 @@ export const mockInterval = (type: IntervalType, duration: number) => ({
1515
id: uid(),
1616
});
1717

18-
class Queries {
19-
protected readonly list: Locator;
20-
protected readonly controls: Locator;
21-
22-
readonly timer: Locator;
18+
interface QueriesOptions {
19+
root?: boolean;
20+
}
2321

22+
class BaseQueries {
23+
#ctxList: Locator[] = [];
24+
#root: Page;
2425
constructor(public readonly page: Page) {
25-
this.list = this.page.getByRole('list', { name: 'Intervals' });
26-
this.timer = this.page.getByRole('timer');
27-
this.controls = this.page.getByRole('group', { name: 'Timer controls' });
26+
this.#root = page;
27+
}
28+
29+
get parent() {
30+
return this.#ctxList.at(-1);
31+
}
32+
33+
get root() {
34+
return this.#root;
35+
}
36+
37+
#getCurrent(fromRoot = false) {
38+
return fromRoot ? this.#root : this.#ctxList.at(-1) || this.#root;
39+
}
40+
41+
getButton(name: string | RegExp, { root = false }: QueriesOptions = {}) {
42+
return this.#getCurrent(root).getByRole('button', { name });
43+
}
44+
45+
async within<L extends Locator>(
46+
base: L,
47+
fn: (base: L) => Promise<void> | void,
48+
) {
49+
this.#ctxList.push(base);
50+
await fn(base);
51+
this.#ctxList.pop();
2852
}
2953

30-
getControl(name: string | RegExp, { context }: { context?: Locator } = {}) {
31-
return (context ?? this.controls).getByRole('button', { name });
54+
static defineWithin<Q extends BaseQueries, L extends Locator>(
55+
srcQuery: Q,
56+
base: L,
57+
) {
58+
return (fn: (base: L) => Promise<void> | void) => srcQuery.within(base, fn);
3259
}
60+
}
61+
62+
class Queries extends BaseQueries {
63+
readonly list: Locator;
64+
65+
readonly timer: Locator;
66+
67+
withinControls: ReturnType<typeof BaseQueries.defineWithin>;
68+
withinSettings: ReturnType<typeof BaseQueries.defineWithin>;
69+
70+
constructor(page: Page) {
71+
super(page);
72+
this.list = page.getByRole('list', { name: 'Intervals' });
73+
this.timer = page.getByRole('timer');
3374

34-
getButton(name: string | RegExp, { context }: { context?: Locator } = {}) {
35-
return (context ?? this.page).getByRole('button', { name });
75+
this.withinControls = BaseQueries.defineWithin(
76+
this,
77+
page.getByRole('group', { name: 'Timer controls' }),
78+
);
79+
80+
this.withinSettings = BaseQueries.defineWithin(
81+
this,
82+
page.getByRole('dialog', { name: 'Settings' }),
83+
);
3684
}
3785

3886
getIntervalList() {
@@ -59,10 +107,6 @@ export class AppPage {
59107
window.localStorage.setItem('intervals', JSON.stringify(intervals));
60108
}, intervals);
61109
}
62-
63-
async withinSettings(fn: (dialog: Locator) => Promise<void> | void) {
64-
await fn(this.page.getByRole('dialog', { name: 'Settings' }));
65-
}
66110
}
67111

68112
export const test = base.extend<{ appPage: AppPage; queries: Queries }>({

tests/settings.spec.ts

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ test.describe('dialog interactions', () => {
77
});
88

99
test('open settings dialog', async ({ page, queries }) => {
10-
await queries.getControl('Settings').click();
10+
await queries.getButton('Settings').click();
1111
await expect(page.getByRole('dialog', { name: 'Settings' })).toBeVisible();
1212
});
1313

1414
test('close settings dialog with button', async ({ queries, page }) => {
15-
await queries.getControl('Settings').click();
15+
await queries.getButton('Settings').click();
1616
await expect(page.getByRole('dialog', { name: 'Settings' })).toBeVisible();
1717

1818
await queries.getButton('Cancel').click();
@@ -22,7 +22,7 @@ test.describe('dialog interactions', () => {
2222
});
2323

2424
test('close settings dialog with key', async ({ queries, page }) => {
25-
await queries.getControl('Settings').click();
25+
await queries.getButton('Settings').click();
2626

2727
const dialog = page.getByRole('dialog', { name: 'Settings' });
2828
await expect(dialog).toBeVisible();
@@ -35,47 +35,47 @@ test.describe('dialog interactions', () => {
3535
test.describe('functionality', () => {
3636
test.beforeEach(async ({ page, queries }) => {
3737
await page.goto('/');
38-
await queries.getControl('Settings').click();
38+
await queries.getButton('Settings').click();
3939
});
40-
test('Type field', async ({ appPage }) => {
41-
await appPage.withinSettings(async (settings) => {
40+
test('Type field', async ({ queries }) => {
41+
await queries.withinSettings(async (settings) => {
4242
const select = settings.getByLabel('Type');
4343
await expect(select).toHaveRole('combobox');
4444

4545
await expect(select).toHaveOptions(['Work', 'ShortBreak', 'LongBreak']);
4646
await expect(select).toHaveSelected('Work');
4747
});
4848
});
49-
test('Duration field', async ({ appPage }) => {
50-
await appPage.withinSettings(async (settings) => {
49+
test('Duration field', async ({ queries }) => {
50+
await queries.withinSettings(async (settings) => {
5151
const duration = settings.getByLabel(/Duration/);
5252
await expect(duration).toHaveAttribute('type', 'number');
5353
await expect(duration).toHaveValue('45');
5454
});
5555
});
56-
test('Update an interval', async ({ appPage, queries }) => {
57-
await appPage.withinSettings(async (settings) => {
56+
test('Update an interval', async ({ queries }) => {
57+
await queries.withinSettings(async (settings) => {
5858
await settings.getByLabel(/Duration/).fill('1');
5959
await settings.getByLabel('Type').selectOption({ label: 'ShortBreak' });
6060

61-
await queries.getButton('Save', { context: settings }).click();
61+
await queries.getButton('Save').click();
6262
});
6363

6464
const newTimer = queries.getIntervalList().first();
6565
await expect(newTimer).toContainText('SB');
6666
await expect(newTimer).toContainText('01:00');
6767
});
68-
test('Add an interval', async ({ appPage, queries }) => {
69-
await appPage.withinSettings(async (settings) => {
70-
await queries.getButton('Add', { context: settings }).click();
68+
test('Add an interval', async ({ queries }) => {
69+
await queries.withinSettings(async (settings) => {
70+
await queries.getButton('Add').click();
7171

7272
const row = settings
7373
.getByRole('group', { name: 'Interval Settings' })
7474
.last();
7575

7676
await row.getByLabel('Type').selectOption({ label: 'ShortBreak' });
7777
await row.getByLabel(/Duration/).fill('20');
78-
await queries.getButton('Save', { context: settings }).click();
78+
await queries.getButton('Save').click();
7979
});
8080

8181
const newTimer = queries.getIntervalList().last();
@@ -91,32 +91,34 @@ test.describe('functionality', () => {
9191
await page.reload();
9292
await expect(queries.getIntervalList()).toHaveCount(2);
9393

94-
await queries.getControl('Settings').click();
94+
await queries.getButton('Settings').click();
9595

96-
await appPage.withinSettings(async (settings) => {
96+
await queries.withinSettings(async (settings) => {
9797
const row = settings
9898
.getByRole('group', { name: 'Interval Settings' })
9999
.first();
100100

101-
await queries.getButton('Delete', { context: row }).click();
102-
await queries.getButton('Save', { context: settings }).click();
101+
await queries.within(row, async () => {
102+
await queries.getButton('Delete').click();
103+
});
104+
105+
await queries.getButton('Save').click();
103106
});
104107

105108
await expect(queries.getIntervalList()).toHaveCount(1);
106109
});
107110

108111
test('Cannot remove the interval when it is the only one', async ({
109-
appPage,
110112
queries,
111113
}) => {
112-
await appPage.withinSettings(async (settings) => {
114+
await queries.withinSettings(async (settings) => {
113115
const row = settings
114116
.getByRole('group', { name: 'Interval Settings' })
115117
.first();
116118

117-
await expect(
118-
queries.getButton('Delete', { context: row }),
119-
).toBeDisabled();
119+
await queries.within(row, async () => {
120+
await expect(queries.getButton('Delete')).toBeDisabled();
121+
});
120122
});
121123
});
122124
});
@@ -125,18 +127,14 @@ test.describe('interactions', () => {
125127
test.beforeEach(async ({ page }) => {
126128
await page.goto('/');
127129
});
128-
test('Saving the intervals reset the timer', async ({
129-
appPage,
130-
queries,
131-
page,
132-
}) => {
133-
await queries.getControl('Play').click();
130+
test('Saving the intervals reset the timer', async ({ queries, page }) => {
131+
await queries.getButton('Play').click();
134132
await page.waitForTimeout(2000);
135-
await queries.getControl('Settings').click();
136-
await appPage.withinSettings(async (settings) => {
137-
await queries.getButton('Save', { context: settings }).click();
133+
await queries.getButton('Settings').click();
134+
await queries.withinSettings(async () => {
135+
await queries.getButton('Save').click();
138136
});
139137

140-
await expect(queries.getControl('Play')).toBeVisible();
138+
await expect(queries.getButton('Play')).toBeVisible();
141139
});
142140
});

tests/timer.spec.ts

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ test.describe('initial state', () => {
1919
});
2020

2121
test('controls', async ({ queries }) => {
22-
await expect(queries.getControl('Play')).toBeVisible();
23-
await expect(queries.getControl('Skip')).toBeVisible();
24-
await expect(queries.getControl('Reset')).toBeVisible();
25-
await expect(queries.getControl('Settings')).toBeVisible();
22+
await queries.withinControls(async () => {
23+
await expect(queries.getButton('Play')).toBeVisible();
24+
await expect(queries.getButton('Skip')).toBeVisible();
25+
await expect(queries.getButton('Reset')).toBeVisible();
26+
await expect(queries.getButton('Settings')).toBeVisible();
27+
});
2628
});
2729
});
2830

@@ -40,57 +42,68 @@ test.describe('functionality', () => {
4042
});
4143

4244
test('play', async ({ queries }) => {
43-
await queries.getControl('Play').click();
45+
await queries.withinControls(async () => {
46+
await queries.getButton('Play').click();
4447

45-
await expect(queries.getControl('Play')).not.toBeVisible();
46-
await expect(queries.getControl('Pause')).toBeVisible();
48+
await expect(queries.getButton('Play')).not.toBeVisible();
49+
await expect(queries.getButton('Pause')).toBeVisible();
50+
});
4751
});
4852

4953
test('pause', async ({ queries }) => {
50-
await queries.getControl('Play').click();
54+
await queries.withinControls(async () => {
55+
await queries.getButton('Play').click();
5156

52-
await expect(queries.getControl('Play')).not.toBeVisible();
53-
await queries.getControl('Pause').click();
54-
await expect(queries.getControl('Play')).toBeVisible();
57+
await expect(queries.getButton('Play')).not.toBeVisible();
58+
await queries.getButton('Pause').click();
59+
await expect(queries.getButton('Play')).toBeVisible();
60+
});
5561
});
5662

5763
test('skip', async ({ queries, page }) => {
5864
await expect(queries.timer).toContainText('01:00');
5965

60-
await queries.getControl('Skip').click();
61-
await page.waitForTimeout(700);
66+
await queries.withinControls(async () => {
67+
await queries.getButton('Skip').click();
68+
await page.waitForTimeout(700);
6269

63-
await expect(queries.timer).toContainText('02:00');
70+
await expect(queries.timer).toContainText('02:00');
71+
});
6472
});
6573

6674
test('skip cycle', async ({ queries, page }) => {
6775
await expect(queries.timer).toContainText('01:00');
6876

69-
await queries.getControl('Skip').click();
70-
await page.waitForTimeout(700);
77+
await queries.withinControls(async () => {
78+
await queries.getButton('Skip').click();
79+
await page.waitForTimeout(700);
7180

72-
await expect(queries.timer).toContainText('02:00');
73-
74-
await queries.getControl('Skip').click();
75-
await page.waitForTimeout(700);
81+
await expect(queries.timer).toContainText('02:00');
7682

83+
await queries.getButton('Skip').click();
84+
await page.waitForTimeout(700);
85+
});
7786
await expect(queries.timer).toContainText('01:00');
7887
});
7988

8089
test('skip when paused', async ({ queries, page }) => {
81-
await queries.getControl('Skip').click();
82-
await page.waitForTimeout(700);
90+
await queries.withinControls(async () => {
91+
await queries.getButton('Skip').click();
92+
await page.waitForTimeout(700);
8393

84-
await expect(queries.timer).toContainText('02:00');
85-
await expect(queries.getControl('Play')).toBeVisible();
94+
await expect(queries.timer).toContainText('02:00');
95+
await expect(queries.getButton('Play')).toBeVisible();
96+
});
8697
});
8798

8899
test('skip when playing', async ({ queries, page }) => {
89-
await queries.getControl('Play').click();
90-
await queries.getControl('Skip').click();
91-
await page.waitForTimeout(700);
92-
93-
await expect(queries.timer).toContainText('02:00');
94-
await expect(queries.getControl('Pause')).toBeVisible();
100+
await queries.withinControls(async () => {
101+
await queries.getButton('Play').click();
102+
await queries.getButton('Skip').click();
103+
await page.waitForTimeout(700);
104+
105+
await expect(queries.timer).toContainText('02:00');
106+
await expect(queries.getButton('Pause')).toBeVisible();
107+
});
95108
});
96109
});

0 commit comments

Comments
 (0)