From 1ddf3b3abfafc058a19deb24227feec1409e1310 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 28 Dec 2021 23:02:53 +0100 Subject: [PATCH] feat: text snapshots, closes #9 --- .../demo/src/__snapshots__/vue.spec.ts.snap | 17 +++ examples/demo/src/vue.spec.ts | 7 +- examples/vue3/src/Hello.spec.ts | 4 +- .../vue3/src/__snapshots__/Hello.spec.ts.snap | 10 ++ packages/peeky-cli/src/bin.ts | 1 + packages/peeky-cli/src/commands/run.ts | 3 + packages/peeky-client/src/apollo.ts | 1 + .../peeky-client/src/features/BaseTab.vue | 2 +- .../src/features/editor/CodeEditor.vue | 73 +++++++++++ .../DiffEditor.vue} | 8 +- .../src/features/snapshot/SnapshotItem.vue | 33 +++++ .../src/features/snapshot/SnapshotView.vue | 117 +++++++++++++++++ .../src/features/test-file/TestFileItem.vue | 1 + .../src/features/test/TestResult.vue | 4 +- .../src/features/test/TestSnapshots.vue | 123 ++++++++++++++++++ .../src/features/test/TestView.vue | 34 ++++- packages/peeky-client/src/router.ts | 5 + packages/peeky-runner/package.json | 4 + packages/peeky-runner/src/index.ts | 1 + packages/peeky-runner/src/message.ts | 4 +- .../src/reporters/console-fancy.ts | 39 +++++- packages/peeky-runner/src/run-all.ts | 13 +- packages/peeky-runner/src/runner.ts | 3 +- .../peeky-runner/src/runtime/run-test-file.ts | 22 +++- .../peeky-runner/src/runtime/run-tests.ts | 15 ++- .../peeky-runner/src/runtime/test-register.ts | 2 + packages/peeky-runner/src/snapshot/format.ts | 31 +++++ packages/peeky-runner/src/snapshot/index.ts | 3 + packages/peeky-runner/src/snapshot/matcher.ts | 106 +++++++++++++++ .../peeky-runner/src/snapshot/plugins/html.ts | 23 ++++ packages/peeky-runner/src/snapshot/read.ts | 28 ++++ packages/peeky-runner/src/snapshot/types.ts | 9 ++ packages/peeky-runner/src/snapshot/util.ts | 19 +++ packages/peeky-runner/src/snapshot/version.ts | 1 + packages/peeky-runner/src/snapshot/write.ts | 34 +++++ packages/peeky-runner/src/stats.ts | 11 ++ packages/peeky-runner/src/types.ts | 15 +++ .../src/generated/nexus-typegen.ts | 49 +++++++ .../peeky-server/src/generated/schema.graphql | 21 +++ packages/peeky-server/src/schema/Run.ts | 38 ++++++ packages/peeky-server/src/schema/Snapshot.ts | 108 +++++++++++++++ packages/peeky-server/src/schema/Test.ts | 5 + packages/peeky-server/src/schema/index.ts | 1 + pnpm-lock.yaml | 69 +++++++++- 44 files changed, 1095 insertions(+), 22 deletions(-) create mode 100644 examples/demo/src/__snapshots__/vue.spec.ts.snap create mode 100644 examples/vue3/src/__snapshots__/Hello.spec.ts.snap create mode 100644 packages/peeky-client/src/features/editor/CodeEditor.vue rename packages/peeky-client/src/features/{test/TestAssertionDiff.vue => editor/DiffEditor.vue} (80%) create mode 100644 packages/peeky-client/src/features/snapshot/SnapshotItem.vue create mode 100644 packages/peeky-client/src/features/snapshot/SnapshotView.vue create mode 100644 packages/peeky-client/src/features/test/TestSnapshots.vue create mode 100644 packages/peeky-runner/src/snapshot/format.ts create mode 100644 packages/peeky-runner/src/snapshot/index.ts create mode 100644 packages/peeky-runner/src/snapshot/matcher.ts create mode 100644 packages/peeky-runner/src/snapshot/plugins/html.ts create mode 100644 packages/peeky-runner/src/snapshot/read.ts create mode 100644 packages/peeky-runner/src/snapshot/types.ts create mode 100644 packages/peeky-runner/src/snapshot/util.ts create mode 100644 packages/peeky-runner/src/snapshot/version.ts create mode 100644 packages/peeky-runner/src/snapshot/write.ts create mode 100644 packages/peeky-server/src/schema/Snapshot.ts diff --git a/examples/demo/src/__snapshots__/vue.spec.ts.snap b/examples/demo/src/__snapshots__/vue.spec.ts.snap new file mode 100644 index 0000000..4f82fd5 --- /dev/null +++ b/examples/demo/src/__snapshots__/vue.spec.ts.snap @@ -0,0 +1,17 @@ +// Peeky snapshots v1.0 + +exports[`vue create vue app 1`] = ` +
+
+ hello +
+
+`; + +exports[`vue create vue app demo 1`] = ` +"Hello" +`; + +exports[`vue create vue app demo 2`] = ` +"Meow" +`; \ No newline at end of file diff --git a/examples/demo/src/vue.spec.ts b/examples/demo/src/vue.spec.ts index 21a3e85..a9b0ad9 100644 --- a/examples/demo/src/vue.spec.ts +++ b/examples/demo/src/vue.spec.ts @@ -13,13 +13,16 @@ describe('vue', () => { msg: 'hello', } }, - template: '
hello
', + template: '
{{ msg }}
', }) console.log(app) expect(typeof app.version).toBe('string') const el = document.createElement('div') document.body.appendChild(el) app.mount(el) - expect(el.innerHTML).toBe('
hello
') + expect(document.body.innerHTML).toMatchSnapshot() + expect('Hello').toMatchSnapshot('demo') + expect('Meow').toMatchSnapshot('demo') + // expect(el.innerHTML).toBe('
hello
') }) }) diff --git a/examples/vue3/src/Hello.spec.ts b/examples/vue3/src/Hello.spec.ts index cdb297b..697adde 100644 --- a/examples/vue3/src/Hello.spec.ts +++ b/examples/vue3/src/Hello.spec.ts @@ -13,8 +13,8 @@ describe('vue + peeky demo', () => { }) expect(wrapper.text()).toContain('4 x 2 = 8') - // Available soon - // expect(wrapper.html()).toMatchSnapshot() + + expect(wrapper.html()).toMatchSnapshot() await wrapper.get('button').trigger('click') diff --git a/examples/vue3/src/__snapshots__/Hello.spec.ts.snap b/examples/vue3/src/__snapshots__/Hello.spec.ts.snap new file mode 100644 index 0000000..0329ba5 --- /dev/null +++ b/examples/vue3/src/__snapshots__/Hello.spec.ts.snap @@ -0,0 +1,10 @@ +// Peeky snapshots v1.0 + +exports[`vue + peeky demo mount component 1`] = ` +
+  4 x 2 = 9
+
+ +`; \ No newline at end of file diff --git a/packages/peeky-cli/src/bin.ts b/packages/peeky-cli/src/bin.ts index 4b2a4bb..3b87d65 100644 --- a/packages/peeky-cli/src/bin.ts +++ b/packages/peeky-cli/src/bin.ts @@ -15,6 +15,7 @@ program.command('run [quickFilter]') .option('-m, --match ', 'Globs to match test files. Example: `peeky run -m "**/*.spec.ts" "**/__tests__/*.ts"`') .option('-i, --ignore ', 'Globs ignore when looking for test files. Example: `peeky run -i "node_modules" "dist/**/*.ts"`') .option('-r, --reporters ', 'Reporters to use. Available: console-fancy, console-json') + .option('-u, --updateSnapshots', 'Update failing snapshots') .action(async (quickFilter, options) => { const { run } = await import('./commands/run.js') return run(quickFilter, options) diff --git a/packages/peeky-cli/src/commands/run.ts b/packages/peeky-cli/src/commands/run.ts index 4c207e1..9fc8de3 100644 --- a/packages/peeky-cli/src/commands/run.ts +++ b/packages/peeky-cli/src/commands/run.ts @@ -21,6 +21,9 @@ export async function run (quickFilter: string, options) { const { stats: { errorSuiteCount } } = await runAllTests(toProgramConfig(finalConfig), { quickTestFilter: quickFilter, + ...pick(options, [ + 'updateSnapshots', + ]), }) if (errorSuiteCount) { diff --git a/packages/peeky-client/src/apollo.ts b/packages/peeky-client/src/apollo.ts index 8ac4dc8..82406d2 100644 --- a/packages/peeky-client/src/apollo.ts +++ b/packages/peeky-client/src/apollo.ts @@ -123,4 +123,5 @@ const cache = new InMemoryCache({ export const apolloClient = new ApolloClient({ link, cache, + connectToDevTools: true, }) diff --git a/packages/peeky-client/src/features/BaseTab.vue b/packages/peeky-client/src/features/BaseTab.vue index cd5597d..e146122 100644 --- a/packages/peeky-client/src/features/BaseTab.vue +++ b/packages/peeky-client/src/features/BaseTab.vue @@ -15,7 +15,7 @@ export default defineComponent({ +import * as monaco from 'monaco-editor' +import { onMounted, ref, watch } from 'vue' +import { onResize } from '../../util/resize' +import '../../util/monaco' +import { useSettings } from '../settings' + +const props = defineProps({ + code: { + type: String, + required: true, + }, +}) + +const el = ref() +let editor: monaco.editor.IEditor + +onMounted(() => { + if (!el.value) return + editor = monaco.editor.create(el.value, { + readOnly: true, + lineNumbers: 'off', + scrollBeyondLastLine: false, + }) + updateEditorModel() + updateEditorTheme() +}) + +/* Model */ + +watch(() => [props.code], () => { + updateEditorModel() +}) + +function updateEditorModel () { + if (editor) { + editor.setModel(monaco.editor.createModel(props.code, props.code.trim().startsWith('<') ? 'html' : 'javascript')) + } +} + +/* Theme */ + +const { settings } = useSettings() + +watch(() => settings.value?.darkMode, () => { + updateEditorTheme() +}) + +function updateEditorTheme () { + if (!editor) return + editor.updateOptions({ + // @ts-ignore + theme: settings.value?.darkMode ? 'peeky-dark' : 'peeky-light', + }) +} + +/* Resize */ + +onResize(el, () => { + if (editor) { + editor.layout() + } +}) + + + diff --git a/packages/peeky-client/src/features/test/TestAssertionDiff.vue b/packages/peeky-client/src/features/editor/DiffEditor.vue similarity index 80% rename from packages/peeky-client/src/features/test/TestAssertionDiff.vue rename to packages/peeky-client/src/features/editor/DiffEditor.vue index 6d0a191..69d4cb7 100644 --- a/packages/peeky-client/src/features/test/TestAssertionDiff.vue +++ b/packages/peeky-client/src/features/editor/DiffEditor.vue @@ -1,6 +1,6 @@ + + diff --git a/packages/peeky-client/src/features/snapshot/SnapshotView.vue b/packages/peeky-client/src/features/snapshot/SnapshotView.vue new file mode 100644 index 0000000..bdb9552 --- /dev/null +++ b/packages/peeky-client/src/features/snapshot/SnapshotView.vue @@ -0,0 +1,117 @@ + + + diff --git a/packages/peeky-client/src/features/test-file/TestFileItem.vue b/packages/peeky-client/src/features/test-file/TestFileItem.vue index 1119e96..4804746 100644 --- a/packages/peeky-client/src/features/test-file/TestFileItem.vue +++ b/packages/peeky-client/src/features/test-file/TestFileItem.vue @@ -13,6 +13,7 @@ const props = defineProps({ props.test?.error?.actual && props.test?.error? - +import { useQuery } from '@vue/apollo-composable' +import gql from 'graphql-tag' +import { useRoute, useRouter } from 'vue-router' +import { computed, defineProps, watch } from 'vue' + +import BaseSplitPane from '../BaseSplitPane.vue' +import SnapshotItem from '../snapshot/SnapshotItem.vue' +import SnapshotView from '../snapshot/SnapshotView.vue' + +const route = useRoute() +const router = useRouter() + +const props = defineProps({ + test: { + type: Object, + required: true, + }, + + suite: { + type: Object, + required: true, + }, +}) + +const { result, refetch } = useQuery(() => gql` + query testLogs ($runId: ID!, $suiteId: ID!, $testId: ID!) { + run (id: $runId) { + id + testSuite: testSuiteById (id: $suiteId) { + id + test: testById (id: $testId) { + id + snapshots { + id + title + content + newContent + line + col + updated + } + } + } + } + } +`, () => ({ + runId: route.params.runId, + suiteId: props.suite.id, + testId: props.test.id, +}), { + fetchPolicy: 'network-only', +}) + +const snapshots = computed(() => result.value?.run?.testSuite?.test?.snapshots ?? []) + +watch(() => props.test.status, () => { + refetch() +}) + +const selectedSnapshot = computed(() => snapshots.value.find((s: any) => s.id === route.query.snapshotId)) + +function selectPrevious () { + let index = snapshots.value.indexOf(selectedSnapshot.value) + index-- + if (index < 0) { + index = snapshots.value.length - 1 + } + router.push({ + query: { + ...route.query, + snapshotId: snapshots.value[index].id, + }, + }) +} + +function selectNext () { + let index = snapshots.value.indexOf(selectedSnapshot.value) + index++ + if (index > snapshots.value.length - 1) { + index = 0 + } + router.push({ + query: { + ...route.query, + snapshotId: snapshots.value[index].id, + }, + }) +} + + + diff --git a/packages/peeky-client/src/features/test/TestView.vue b/packages/peeky-client/src/features/test/TestView.vue index f883981..bc384ab 100644 --- a/packages/peeky-client/src/features/test/TestView.vue +++ b/packages/peeky-client/src/features/test/TestView.vue @@ -22,6 +22,8 @@ fragment testView on Test { ...testResultError } hasLogs + snapshotCount + failedSnapshotCount } ${errorFragment} ` @@ -139,14 +141,20 @@ mutation openInEditor ($id: ID!, $line: Int!, $col: Int!) { -