Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[chore] first steps for getting a test setup #12

Merged
merged 49 commits into from
Aug 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
177d291
first steps for getting a test setup
MathiasWP Jul 21, 2022
7fead81
Merge branch 'main' into test
MathiasWP Jul 21, 2022
c1fa289
add new clipboard fix from main
MathiasWP Jul 21, 2022
1d81eca
format
MathiasWP Jul 21, 2022
542bbb2
fix readme
MathiasWP Jul 21, 2022
1251170
fixed nasty merge conflict
MathiasWP Jul 21, 2022
d3d9038
fix incomplete reversion of clone fn
nikolai-cc Jul 25, 2022
061b11b
fix unresolved merge conflict
nikolai-cc Jul 25, 2022
bcf8b68
fix unresolved merge conflict
nikolai-cc Jul 25, 2022
6c4e0e0
fix broken meta imports
nikolai-cc Jul 25, 2022
66cd8b4
cleanup gitignore
nikolai-cc Jul 25, 2022
24a6cd3
vitest: use include over exclude pattern
nikolai-cc Jul 25, 2022
39077a9
cleanup npm test:* commands
nikolai-cc Jul 25, 2022
c4187d0
exclude vscode workspace settings
nikolai-cc Jul 25, 2022
6ab8737
change template dir
nikolai-cc Jul 25, 2022
a36b198
update playwright config
nikolai-cc Jul 25, 2022
77fbcf0
include test/ folder in tsconfig
nikolai-cc Jul 25, 2022
16ac4ab
change playwright template dir
nikolai-cc Jul 25, 2022
39684b1
remove superfluous test and use fs.existsSync
nikolai-cc Jul 25, 2022
1dfbcd8
use $lib beause we can now
nikolai-cc Jul 25, 2022
3717240
update clickoutside spec
nikolai-cc Jul 25, 2022
11852cc
setup checks for .svelte-kit/tsconfig
nikolai-cc Jul 25, 2022
b963d67
run test:setup for vitest
nikolai-cc Jul 25, 2022
02928b9
add random test
nikolai-cc Jul 25, 2022
1c01c50
better name
nikolai-cc Jul 25, 2022
faa8fef
move playwright-report into test folder
nikolai-cc Jul 25, 2022
9a7a03d
fix broken include config
nikolai-cc Aug 2, 2022
22fdf74
move playwright config
nikolai-cc Aug 5, 2022
98e14e3
move vitest config
nikolai-cc Aug 5, 2022
ba1da75
add playwright template
nikolai-cc Aug 5, 2022
40c4a4e
update playwright cache location
nikolai-cc Aug 5, 2022
379443a
add test cache cleaning script
nikolai-cc Aug 5, 2022
0261899
make files outside src are evaluated by typescript
nikolai-cc Aug 5, 2022
ce2cbb1
add info on playwright cache
nikolai-cc Aug 5, 2022
c6882d4
move tests to test/tests folder
nikolai-cc Aug 5, 2022
2435c0f
add env mock
nikolai-cc Aug 5, 2022
a37362f
add $app mock
nikolai-cc Aug 5, 2022
9b083a3
add test for action:active
nikolai-cc Aug 5, 2022
bc69337
small cleanup
nikolai-cc Aug 5, 2022
cb9047c
add separate tests for event and callback for action/clickoutside
nikolai-cc Aug 10, 2022
13e0ab3
fix typo
nikolai-cc Aug 10, 2022
3e53e48
add clipboard tests
nikolai-cc Aug 10, 2022
df0194a
add $app mocks to vitest
nikolai-cc Aug 10, 2022
57a8dbd
add mocks and imports
nikolai-cc Aug 10, 2022
452f6de
fix $lib imports
nikolai-cc Aug 10, 2022
e9f4298
add testing README
nikolai-cc Aug 10, 2022
9215baa
fix accidental catch 22
nikolai-cc Aug 10, 2022
a6385cb
fix test for random
nikolai-cc Aug 10, 2022
df9d427
add resettable tests
nikolai-cc Aug 10, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ node_modules
.env
.env.*
!.env.example
.vscode

# used for janky brain farts, don't commit
/src/routes/temp
/src/routes/temp

# test files
/test-results/
/test/playwright/report/
/test/playwright/.cache/
1,205 changes: 797 additions & 408 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
"url": "https://github.com/nikolai-cc/svu/issues"
},
"scripts": {
"test": "npm run test:vitest && npm run test:playwright",
"test:clean": "rm -rf ./test/playwright/.cache",
"test:setup": "tsm ./test/setup.ts",
"test:vitest": "npm run test:setup && vitest run -c test/vitest.config.ts",
"test:playwright": "npm run test:setup && playwright test -c test/playwright.config.ts",
"dev": "vite dev",
"build": "vite build",
"package": "svelte-kit package",
Expand All @@ -24,6 +29,7 @@
"format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. ."
},
"devDependencies": {
"@playwright/experimental-ct-svelte": "^1.23.4",
"@sveltejs/adapter-auto": "^1.0.0-next.61",
"@sveltejs/adapter-static": "^1.0.0-next.37",
"@sveltejs/kit": "^1.0.0-next.377",
Expand All @@ -32,6 +38,7 @@
"eslint": "^8.20.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-svelte3": "^4.0.0",
"fast-glob": "^3.2.11",
"mdsvex": "^0.10.6",
"prettier": "^2.7.1",
"prettier-plugin-svelte": "^2.5.0",
Expand All @@ -40,8 +47,10 @@
"svelte-preprocess": "^4.10.7",
"svelte2tsx": "^0.5.11",
"tslib": "^2.3.1",
"tsm": "^2.2.2",
"typescript": "^4.7.4",
"vite": "^3.0.0"
"vite": "^3.0.0",
"vitest": "^0.18.1"
},
"module": "./index.js",
"exports": {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/action/clickoutside.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { listen, noop } from '$lib/meta/index.js';
import { listen, noop } from '../meta/index.js';

/**
* Executes a function when clicking anywhere but on the target node.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/action/clipboard.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { listen } from '$lib/meta/index.js';
import { listen } from '../meta/index.js';

/**
* Copies the textContent of the element (or a specified target) to clipboard on click.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/action/download.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { listen } from '$lib/meta/index.js';
import { listen } from '../meta/index.js';

/**
* Downloads the textContent of the element (or a specified target) into a .txt file on click.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/action/draggable.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { listen } from '$lib/meta/index.js';
import { listen } from '../meta/index.js';

/**
* Allows positioning of an element by dragging it from the element or an optional handle.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/action/focus.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { noop } from '$lib/meta/index.js';
import { noop } from '../meta/index.js';

/**
* Focuses element when it mounts. Only works on focusable elements.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/action/focustrap.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { noop, listen } from '$lib/meta/index.js';
import { noop, listen } from '../meta/index.js';

// This list originates from: https://stackoverflow.com/a/30753870
const FOCUSABLE = `
Expand Down
4 changes: 2 additions & 2 deletions src/lib/action/keyboard.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { listen, capitalise } from '$lib/meta/index.js';
import { listen, noop, capitalise } from '../meta/index.js';

export type keyMap = { [key: string]: (...params: any) => any };
export type keyMap = { [key: string]: Function };

/**
* Takes an `keyboard shortcut` string: e.g. `'shift+cmd+a'` and returns a string that normalises `meta`/`cmd`/`win` to `'Super'`,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/action/onclose.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { listen, noop } from '$lib/meta/index.js';
import { listen, noop } from '../meta/index.js';

/**
* Executes an optional fuction on the onclose event, and displays an 'are you sure' modal.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/action/press.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { listen, noop, timeout } from '$lib/meta/index.js';
import { listen, noop, timeout } from '../meta/index.js';

/**
* Dispatches a press event or calls a handler if pressed down for duration milliseconds.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/action/resize.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { noop } from '$lib/meta/index.js';
import { noop } from '../meta/index.js';

/**
* Dispatches an event or calls a handler if an element is resized.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/action/select.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { listen } from '$lib/meta/index.js';
import { listen } from '../meta/index.js';

/**
* Selects the content of the element (or a specified target) on click.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/action/themetoggle.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { listen, noop } from '$lib/meta/index.js';
import { listen, noop } from '../meta/index.js';

/**
* Theme Toggler.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/action/timedclick.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { listen, noop, timeout } from '$lib/meta/index.js';
import { listen, noop, timeout } from '../meta/index.js';

/**
* Dispatches an event or calls a handler if released within 'duration' milliseconds.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/client/mouse.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { browser } from '$app/env';
import { derived, writable } from 'svelte/store';
import { listen } from '$lib/meta/index.js';
import { listen } from '../meta/index.js';

const create = (prop: 'clientX' | 'clientY') => {
const { subscribe, set } = writable(0);
Expand Down
2 changes: 1 addition & 1 deletion src/lib/client/window.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { browser } from '$app/env';
import { derived, writable } from 'svelte/store';
import { listen } from '$lib/meta/index.js';
import { listen } from '../meta/index.js';

const createSize = (prop: 'innerWidth' | 'innerHeight') => {
const { subscribe, set } = writable(0);
Expand Down
26 changes: 12 additions & 14 deletions src/lib/meta/clone.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
/**
* Function that deep clones any object
* Function that deep clones any object up to a maximum recursion depth.
*/
export const clone = typeof structuredClone === 'function' ? structuredClone : _clone;
export const clone = (obj: any, depth: number = Infinity) => {
let parents: any[] = [];
let children: any[] = [];

function _clone(obj: any) {
const parents: any[] = [];
const children: any[] = [];

const __clone = (obj: any) => {
const _clone = (obj: any, depth: number) => {
if (typeof obj !== 'object') {
return obj;
}
Expand All @@ -28,8 +26,8 @@ function _clone(obj: any) {
} else if (obj instanceof Promise) {
child = new Promise((res, rej) =>
obj.then(
(v) => res(__clone(v)),
(e) => rej(__clone(e))
(v) => res(_clone(v, depth - 1)),
(e) => rej(_clone(e, depth - 1))
)
);
} else {
Expand All @@ -44,19 +42,19 @@ function _clone(obj: any) {

if (obj instanceof Map) {
for (let [k, v] of obj) {
child.set(k, __clone(v));
child.set(k, _clone(v, depth - 1));
}
} else if (obj instanceof Set) {
for (let v of obj) {
child.add(__clone(v));
child.add(_clone(v, depth - 1));
}
} else {
for (let key in obj) {
child[key] = __clone(obj[key]);
child[key] = _clone(obj[key], depth - 1);
}
}
return child;
};

return __clone(obj);
}
return _clone(obj, depth);
};
2 changes: 1 addition & 1 deletion src/lib/meta/memoize.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { stringify } from './json';
import { stringify } from './json.js';

/**
* Function that caches the results of the passed function to prevent double (expensive) computations.
Expand Down
6 changes: 3 additions & 3 deletions src/lib/meta/random.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
* Passing in a single parameter returns a random integer between 0 and the provided value.
*/
export const random = (min: number, max?: number) => {
min = max ? min : 0;
max = max ? max : min;
return Math.floor(Math.random() * (max - min + 1)) + min;
const _min = max ? min : 0;
const _max = max ? max : min;
return Math.floor(Math.random() * (_max - _min + 1)) + _min;
};

/** Flip a coin */
Expand Down
2 changes: 1 addition & 1 deletion src/lib/store/localstore.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { browser } from '$app/env';
import { noop, stringify, parse } from '$lib/meta/index.js';
import { noop, stringify, parse } from '../meta/index.js';
import { writable } from 'svelte/store';

/**
Expand Down
2 changes: 1 addition & 1 deletion src/lib/store/mediaquery.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { listen } from '$lib/meta';
import { listen } from '../meta/index.js';
import { browser } from '$app/env';
import { writable, type Readable } from 'svelte/store';

Expand Down
2 changes: 1 addition & 1 deletion src/lib/store/resettable.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { writable, type StartStopNotifier } from 'svelte/store';
import { clone } from '$lib/meta/index.js';
import { clone } from '../meta/index.js';

/**
* Resettable writable store. Allows any values (including objects).
Expand Down
2 changes: 1 addition & 1 deletion src/lib/svelte/client/mouse.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { derived, writable } from 'svelte/store';
import { listen } from '$lib/meta/index.js';
import { listen } from '../../meta/index.js';

const create = (prop: 'clientX' | 'clientY') => {
const { subscribe, set } = writable(0);
Expand Down
2 changes: 1 addition & 1 deletion src/lib/svelte/client/window.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { derived, writable } from 'svelte/store';
import { listen } from '$lib/meta/index.js';
import { listen } from '../../meta/index.js';

const createSize = (prop: 'innerWidth' | 'innerHeight') => {
const { subscribe, set } = writable(0);
Expand Down
64 changes: 64 additions & 0 deletions test/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import type { PlaywrightTestConfig } from '@playwright/experimental-ct-svelte';
import { devices } from '@playwright/experimental-ct-svelte';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

/**
* See https://playwright.dev/docs/test-components
*/
const config: PlaywrightTestConfig = {
testDir: 'tests',
snapshotDir: '__snapshots__',
fullyParallel: true,
testMatch: '**/*.spec.ts',
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
reporter: [['html', { outputFolder: 'playwright/report' }]],
use: {
trace: 'on-first-retry',
ctPort: 3100,
ctViteConfig: {
resolve: {
alias: {
// Setup the built-in $lib alias in SvelteKit
'$lib': resolve(__dirname, '../src/lib'),
// Replace $app with our mocked variant.
'$app': resolve(__dirname, 'playwright/mock/app'),
}
}
},

ctTemplateDir: 'playwright/template',
ctCacheDir: 'playwright/.cache',
},

projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome']
}
},
{
name: 'firefox',
use: {
...devices['Desktop Firefox']
}
},
{
name: 'webkit',
use: {
...devices['Desktop Safari']
}
}
]
};

export default config;
3 changes: 3 additions & 0 deletions test/playwright/mock/app/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { readable } from 'svelte/store';

export const browser = readable(true);
10 changes: 10 additions & 0 deletions test/playwright/mock/app/stores.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { readable, writable } from 'svelte/store';

export const page = writable({
error: null,
params: {},
routeId: '',
status: 200,
stuff: {},
url: new URL('http://svu.dev')
})
12 changes: 12 additions & 0 deletions test/playwright/template/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Testing Page</title>
</head>
<body>
<div id="root"></div>
</body>
<script type="module" src="./index.ts"></script>
</html>
Empty file.
35 changes: 35 additions & 0 deletions test/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Testing svu

You'll find everything related to testing in the `/test` folder. In order to fully test every svu we make use of [Vitest](https://vitest.dev) and [Playwright CT](https://playwright.dev/docs/test-components). Vitests allows us to perform code tests, while Playwright allows us to test components and actions in a real browser environment.

## Writing tests

The `test/tests` folder contains all tests. This folder is structured the same way as the `$lib` folder, so if multiple actions are combined in a single module (e.g. `copy` and `paste` are found in `$lib/clipboard`), create a single test folder (`/test/tests/clipboard`) for them as well.

- Files named `*.spec.ts` are run with Playwright CT.
- Files named `*.test.ts` are run with Vitest.

### Testing with Playwright

E.g. in order to test an action, define a `Component.svelte` that implements the action. Import this component in your `action.spec.ts` file test it there.

The real SvelteKit context (and thus `$app`) is not available in these tests. You can import things from `$app` like you would in SvelteKit, though it resolves to `/test/playwright/mock/app`. There you will find a mocked version of the relevant stores. Feel free to add more if you deem it nessecary. Keep in mind that many `readable` stores are implemented as `writable`, in order to enable us to do things like faking browser navigation by updating the `$page` store in order to test the `active` action. Similarly, feel free to change a mocked store from `readable` to `writable` if a test requires it.

### Testing with Vitest

E.g. in order to test a meta function, simply create a `function.test.ts` file that describes your tests.

Similarly to Playwright, no SvelteKit context is available. You will probably not need to import from `$app`, though a mocked variant is available here as well. See also `/test/vitest/setup.ts`.

## Running tests

The following commands are available:

- `npm run test` runs all tests with both Vitest and Playwright.
- `npm run test:vitest` runs Vitest only.
- `npm run test:playwright` runs Playwright only.
- `npm run test:clean` clears the test cache (see below).

## Troubleshooting:

Having trouble testing with Playwright after tweaking a `./Component.svelte` file? This might well be a cache error. You can remove the `/test/playwright/.cache` folder or simply run `npm run test:clean` (which will do that for you).
Loading