* chore: add Nx Cloud (#26712) * chore: add empty nx.json [run ci] * chore: add nx cloud runner [run ci] * chore: add nx-cloud dep [run ci] * chore: update local nx cloud accessToken to be read-only * feat: update git related messages for runs and debug (#26758) * feat(app): update DebugError copy * feat: set isUsingGit project flag and consume in DebugContainer * feat(app): update not using git icon for DebugError * feat(app): displays alert on runs page when not using git * feat(app): add component for when no runs for current branch * feat(app): add warning for no runs for branch on runs container * chore: add feat to CHANGELOG * chore: remove logged status value * chore: resolve import from merge conflict * test(app): stub branch name for e2e runs spec * chore: add line break in changelog entry * chore: cleanup PR * chore: fix i18n import for DebugBranchError * chore: add utm and update Warning links to inline * chore: capitalize Git in i18n * ref: warning liink * test: add i18n to tests * test(app): change utm_source assertions * chore: cleanup pr * chore: remove unused prop * test(app): remove no git warning when moving to runs page in e2e * chore: change template logic * chore: remove duplicate RUNS_TAB_MEDIUM const * Changed Debug test assertion and reordered new components for Debug --------- Co-authored-by: Stokes Player <stokes.player@gmail.com> * chore: rename video processing events to capture/compress (#26800) * chore: change processing nomenclature to compressing when printing the run. * chore: rename 'capturing of' to 'capturing' * chore: rename upload results to upload screenshots & videos (#26811) * chore: rename upload results to upload screenshots & videos * run ci * chore: capture versions of relevant dependencies with `x-dependencies` header (#26814) * chore: update changlelog script to handle revert pr ref (#26801) * fix: Correct typescript scaffold dependency (#26815) * fix: correct typescript scaffold dependency (#26204) * add changelog * Update change log for PR comment Co-authored-by: Mike Plummer <mike-plummer@users.noreply.github.com> --------- Co-authored-by: Mike Plummer <mike-plummer@users.noreply.github.com> Co-authored-by: Mark Noonan <mark@cypress.io> * chore: 12.13.0 prep (#26833) * chore: 12.13.0 release (#26834) * chore: 12.13.0 changelog fix * remove pending, bump version * fix typo * chore: release @cypress/vite-plugin-cypress-esm-v1.0.1 [skip ci] * chore: Implement runSpec mutation (#26782) * chore: replace gitter badge with discord on readme (#26771) * chore: add GraphQL mutation for sending system notifications via Electron (#26773) * fix: upgrade typescript from 4.7.4 to 4.9.5 (#26826) Snyk has created this PR to upgrade typescript from 4.7.4 to 4.9.5. See this package in npm: See this project in Snyk: https://app.snyk.io/org/cypress-opensource/project/d5b36925-e6ee-455d-9649-6560a9aca413?utm_source=github&utm_medium=referral&page=upgrade-pr * test: fix 2 broken tests for Windows (#26854) * Update stale_issues_and_pr_cleanup.yml Upped the number of operations per run. Have been manually doing that so this job can get through all the issues in the repo with no problems. * chore(dep): [Snyk] Upgrade vite from 2.9.13 to 2.9.15 (#26830) Co-authored-by: Ben M <benm@cypress.io> * Update triage_add_to_project.yml * chore: fix minor background color styling in debug results component (#26887) * Update stale_issues_and_pr_cleanup.yml stalebot was incorrectly configured to run in debug mode. I have updated the default to run in normal mode when running scheduled * chore: Deprecate @cypress/xpath package (#26893) * chore: add telemetry realworld app (#26896) * chore: capture telemetry for realworld app maybe * idk what i was doing * setup record key and telemetry * testing * override project id * some times we just need a little context. * Adding tests * Adding comment * fix yarn lock * Trying this.... * fix tests? --------- Co-authored-by: Jordan <jordan@jpdesigning.com> Co-authored-by: Stokes Player <stokes.player@gmail.com> Co-authored-by: Bill Glesias <bglesias@gmail.com> Co-authored-by: Adam Stone-Lord <adams@cypress.io> Co-authored-by: Emily Rohrbough <emilyrohrbough@users.noreply.github.com> Co-authored-by: Dave Kasper <dave.m.kasper@gmail.com> Co-authored-by: Mike Plummer <mike-plummer@users.noreply.github.com> Co-authored-by: Mark Noonan <mark@cypress.io> Co-authored-by: Chris Breiding <chrisbreiding@users.noreply.github.com> Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net> Co-authored-by: Ely Lucas <ely@meta-tek.net> Co-authored-by: Snyk bot <snyk-bot@snyk.io> Co-authored-by: Stokes Player <stokes@cypress.io> Co-authored-by: Ben M <benm@cypress.io> Co-authored-by: Jennifer Shehane <jennifer@cypress.io>
@packages/data-context
Centralized data access for the Cypress application
Directories & Concepts
There are several directories in src:
actionscodegendatagensourcesutil
The main ones you need to know about are data, sources and actions.
Here are some general guidelines associated with each, and an example showing how they are used together.
Data
This contains the interfaces that describe the top level data (called coreData) that is exposed and used by launchpad and app. Secondary data that isn't exposed to the outside world (temporary states, flags, etc) is usually in a Source. Sources are also used to derive data.
If you want to update Data, you use an Action (see below).
Sources
The sources directory contains what can be thought of as "read only" and "derived" data. Each one is namespaced based on the kind of data it's associated with, for example Project, Browser, Settings, etc. Sources can access the ctx (type DataContext, see DataContext.ts), using this.ctx.
If you want to update something in a Source, or in coreData, you want to do it using an Action.
Actions
Actions are where mutative and destructive operations live. To make this predictable and changes each to track, updating this.ctx.coreData should be done via an Action and use this.ctx.update, which receives the current coreData as the first argument.
Example
In this example, we will load some specs for a project and persist them. We will use a Source to derive any specs with the characters "foo" in the filename. This shows how Data, Sources and Actions are connected.
1. Define Data data/coreData
First we define the type in CoreDataShape and set the initial value in makeCoreData.
export interface CoreDataShape {
specs: string[]
}
// ...
export function makeCoreData (modeOptions: Partial<AllModeOptions> = {}): CoreDataShape {
return {
// ...
specs: [],
}
}
This is where the actual value will be saved.
2. Define Action to Update Specs
We need some way to update the value. For this, we are defining a new SpecActions class inside of actions and updating the coreData with this.ctx.update.
import type { DataContext } from '..'
import globby from 'globby'
export class SpecActions {
constructor (private ctx: DataContext) {}
async findSpecs () {
const specs = await globby('./**/*.spec.js')
this.ctx.update(coreData => {
coreData.specs = specs
})
}
}
Note: If you added a new Action file, you will also need to add it to DataActions.ts, although this isn't very common.
import type { DataContext } from '.'
import {
// ...
SpecActions
} from './actions'
import { cached } from './util'
export class DataActions {
constructor (private ctx: DataContext) {}
// ...
@cached
get specs () {
return new SpecActions(this.ctx)
}
}
3. Derive the Data with a Source
In this example we only want to expose specs with foo in the name. We can derive this using a Source. This will be a new Source call SpecDataSource, but you can use an existing one if it makes sense.
import type { DataContext } from '..'
export class SpecDataSource {
constructor (private ctx: DataContext) {}
fooSpecs () {
return this.ctx.coreData.specs.find(spec => spec.includes('foo'))
}
}
If you added a new Source, you need to add it to DataContext.ts.
import { SpecDataSource } from './sources/SpecDataSource'
export class DataContext {
// ...
@cached
get specs () {
return new SpecDataSource(this)
}
}
4. (Bonus) Expose via GraphQL
You might want to expose your new Data or Source via GraphQL. It's easy, since GraphQL also has access ctx as the third argument to the resolvers. For example, we can expose specs and fooSpecs in gql-Query.ts like this:
export const Query = objectType({
definition (t) {
// ...
t.list.string('specs', {
description: 'A list of specs',
resolve: (source, args, ctx) => {
return ctx.coreData.specs
},
})
t.list.string('fooSpecs', {
description: 'A list of specs containing foo',
resolve: (source, args, ctx) => {
return ctx.specs.fooSpecs()
},
})
}
})