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

feat(app): persist current spec in data context, update runner workflow for demo #18406

Merged
merged 11 commits into from
Oct 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions packages/app/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ declare global {
*/
AutIframe: any
Reporter: any
shortcuts: {
stop: () => void
}
}
}
}
2 changes: 2 additions & 0 deletions packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@
"@urql/vue",
"@vueuse/core",
"lodash",
"mobx",
"nanoid",
"vue",
"vue-toast-notification"
]
Expand Down
7 changes: 7 additions & 0 deletions packages/app/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,10 @@
<!-- </keep-alive> -->
</router-view>
</template>

<style>
.reporter {
position: relative;
width: 100%;
}
</style>
61 changes: 24 additions & 37 deletions packages/app/src/pages/Runner/[...all].vue
Original file line number Diff line number Diff line change
@@ -1,47 +1,34 @@
<template>
<div>
<h2>Runner Page</h2>

<div v-once>
<div :id="RUNNER_ID" />
<div :id="REPORTER_ID" />
</div>
</div>
<Runner
v-if="query.data.value?.app?.activeProject"
:gql="query.data.value.app?.activeProject?.currentSpec"
/>
</template>

<script lang="ts" setup>
import { onMounted } from 'vue'
import type { SpecFile } from '@packages/types/src'
import { UnifiedRunnerAPI } from '../../runner'
import { REPORTER_ID, RUNNER_ID } from '../../runner/utils'
import { useRoute } from 'vue-router'

onMounted(() => {
UnifiedRunnerAPI.initialize(executeSpec)
})

const route = useRoute()

function executeSpec () {
const absolute = route.hash.slice(1)

if (absolute) {
// @ts-ignore
execute({
absolute,
relative: `src/Basic.spec.tsx`,
name: `Basic.spec.tsx`,
})
import { gql } from '@urql/core'
import { useQuery } from '@urql/vue'
import { Runner_AllDocument } from '../../generated/graphql'
import Runner from '../../runs/Runner.vue'

gql`
query Runner_All {
app {
activeProject {
id
currentSpec {
...CurrentSpec_Runner
}
}
}
}
`

const execute = (spec?: SpecFile) => {
if (!spec) {
return
}

UnifiedRunnerAPI.executeSpec(spec)
}
// network-only - we do not want to execute a stale spec
const query = useQuery({
query: Runner_AllDocument,
requestPolicy: 'network-only',
})
</script>

<route>
Expand Down
4 changes: 1 addition & 3 deletions packages/app/src/pages/Specs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ const props = defineProps<{

<style>
iframe {
border: 5px solid black;
margin: 10px;
background: lightgray;
width: 100%;
}
</style>
18 changes: 5 additions & 13 deletions packages/app/src/runner/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,9 @@
*/
import { store, Store } from '../store'
import { injectBundle } from './injectBundle'
import type { SpecFile } from '@packages/types/src/spec'
import type { BaseSpec } from '@packages/types/src/spec'
import { UnifiedReporterAPI } from './reporter'
import { getRunnerElement } from './utils'

function empty (el: HTMLElement) {
while (el.lastChild) {
if (el && el.firstChild) {
el.removeChild(el.firstChild)
}
}
}
import { getRunnerElement, empty } from './utils'

const randomString = `${Math.random()}`

Expand All @@ -52,7 +44,7 @@ function setupRunner (done: () => void) {
/**
* Get the URL for the spec. This is the URL of the AUT IFrame.
*/
function getSpecUrl (namespace: string, spec: SpecFile, prefix = '') {
function getSpecUrl (namespace: string, spec: BaseSpec, prefix = '') {
return spec ? `${prefix}/${namespace}/iframes/${spec.absolute}` : ''
}

Expand All @@ -71,7 +63,7 @@ function teardownSpec (store: Store) {
* Cypress on it.
*
*/
function setupSpec (spec: SpecFile) {
function setupSpec (spec: BaseSpec) {
// @ts-ignore - TODO: figure out how to manage window.config.
const config = window.config

Expand Down Expand Up @@ -136,7 +128,7 @@ function initialize (ready: () => void) {
* 5. Setup the spec. This involves a few things, see the `setupSpec` function's
* description for more information.
*/
async function executeSpec (spec: SpecFile) {
async function executeSpec (spec: BaseSpec) {
store.setSpec(spec)

await UnifiedReporterAPI.resetReporter()
Expand Down
42 changes: 26 additions & 16 deletions packages/app/src/runner/injectBundle.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
function injectReporterStyle () {
const style = document.createElement('style')

style.innerText = `
.reporter {
min-height: 0;
width: 300px;
left: 750px;
position: absolute;
}
`

document.head.appendChild(style)
}
// function injectReporterStyle () {
// const style = document.createElement('style')

// style.innerText = `
// .reporter {
// min-height: 0;
// width: 300px;
// left: 750px;
// position: absolute;
// }
// `

// document.head.appendChild(style)
// }

export async function injectBundle (ready: () => void) {
const src = '/__cypress/runner/cypress_runner.js'

const alreadyInjected = document.querySelector(`script[src="${src}"]`)

if (alreadyInjected) {
ready()

return
}

const response = await window.fetch('/api')
const data = await response.json()
const script = document.createElement('script')

script.src = '/__cypress/runner/cypress_runner.js'
script.src = src
script.type = 'text/javascript'

const link = document.createElement('link')
Expand All @@ -29,7 +39,7 @@ export async function injectBundle (ready: () => void) {
document.head.appendChild(script)
document.head.appendChild(link)

injectReporterStyle()
// injectReporterStyle()

script.onload = () => {
// @ts-ignore - just stick config on window until we figure out how we are
Expand Down
8 changes: 8 additions & 0 deletions packages/app/src/runner/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,11 @@ export function getRunnerElement () {
export function getReporterElement () {
return getElementById(REPORTER_ID)
}

export function empty (el: HTMLElement) {
while (el.lastChild) {
if (el && el.firstChild) {
el.removeChild(el.firstChild)
}
}
}
74 changes: 74 additions & 0 deletions packages/app/src/runs/Runner.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<template>
<div>
<div v-once>
<div class="flex">
<div :id="RUNNER_ID" />
<div :id="REPORTER_ID" />
</div>
</div>
</div>
</template>

<script lang="ts" setup>
import { onBeforeUnmount, onMounted } from 'vue'
import { UnifiedRunnerAPI } from '../runner'
import { REPORTER_ID, RUNNER_ID, getRunnerElement, getReporterElement, empty } from '../runner/utils'
import { gql } from '@urql/core'
import type { CurrentSpec_RunnerFragment } from '../generated/graphql'

gql`
fragment CurrentSpec_Runner on Spec {
id
relative
absolute
name
}
`

const props = defineProps<{
gql: CurrentSpec_RunnerFragment | null
}>()

onMounted(() => {
UnifiedRunnerAPI.initialize(execute)
})

onBeforeUnmount(() => {
// For now we clean up the AUT and Reporter every time we leave the route.
// In the long term, we really should use <keep-alive> and maintain the state
// For now, this is much more simple.
empty(getRunnerElement())
window.UnifiedRunner.shortcuts.stop()
empty(getReporterElement())
})

const execute = () => {
if (!props.gql) {
return
}

UnifiedRunnerAPI.executeSpec(props.gql)
}
</script>

<style scoped>
#unified-runner {
position: relative;
flex-grow: 1;
margin: 20px;
box-shadow: 0px 0px 5px 0 black;
padding: 10px;
}

#unified-reporter {
position: relative;
width: 300px;
height: 100vh;
}
</style>

<route>
{
name: "Runner"
}
</route>
46 changes: 33 additions & 13 deletions packages/app/src/specs/SpecsList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,41 @@
<div>{{ t('specPage.componentSpecsHeader') }}</div>
<div>{{ t('specPage.gitStatusHeader') }}</div>
</div>
<router-link
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now just using gql as the source of truth, not sure if there's a specific reason we need to keep the current spec in the URL or not 🤔

<button
v-for="spec in filteredSpecs"
v-slot="{ navigate }"
:key="spec.node.id"
:to="path(spec)"
class="text-left"
@click.prevent="selectSpec(spec)"
>
<SpecsListRow
:gql="spec"
@click="navigate"
@keypress.enter="navigate"
/>
</router-link>
<SpecsListRow :gql="spec" />
</button>
</div>
</div>
</template>

<script setup lang="ts">
import SpecsListHeader from './SpecsListHeader.vue'
import SpecsListRow from './SpecsListRow.vue'
import { gql } from '@urql/vue'
import { gql, useMutation } from '@urql/vue'
import { computed, ref } from 'vue'
import type { Specs_SpecsListFragment, SpecNode_SpecsListFragment } from '../generated/graphql'
import { Specs_SpecsListFragment, SpecNode_SpecsListFragment, SpecsList_SetCurrentSpecDocument } from '../generated/graphql'
import { useI18n } from '@cy/i18n'
import { useRouter } from 'vue-router'

const { t } = useI18n()
const path = (spec: SpecNode_SpecsListFragment) => `/runner/#${spec.node.absolute}`

gql`
mutation SpecsList_SetCurrentSpec($id: ID!) {
setCurrentSpec(id: $id) {
currentSpec {
id
relative
absolute
name
}
}
}
`

gql`
fragment SpecNode_SpecsList on SpecEdge {
Expand All @@ -53,7 +62,7 @@ fragment Specs_SpecsList on App {
activeProject {
id
projectRoot
specs(first: 10) {
specs(first: 25) {
edges {
...SpecNode_SpecsList
}
Expand All @@ -62,6 +71,17 @@ fragment Specs_SpecsList on App {
}
`

const setSpecMutation = useMutation(SpecsList_SetCurrentSpecDocument)

const router = useRouter()

async function selectSpec (spec: SpecNode_SpecsListFragment) {
const { id } = spec.node

await setSpecMutation.executeMutation({ id })
router.push('runner')
}

const props = defineProps<{
gql: Specs_SpecsListFragment
}>()
Expand Down
Loading