diff --git a/circle.yml b/circle.yml index 39e4681f3f9b..9af034d3404b 100644 --- a/circle.yml +++ b/circle.yml @@ -27,7 +27,7 @@ mainBuildFilters: &mainBuildFilters branches: only: - develop - - issue-22147-nohoist + - global-mode-issue # usually we don't build Mac app - it takes a long time # but sometimes we want to really confirm we are doing the right thing @@ -36,8 +36,7 @@ macWorkflowFilters: &darwin-workflow-filters when: or: - equal: [ develop, << pipeline.git.branch >> ] - - equal: [ linux-arm64, << pipeline.git.branch >> ] - - equal: [ 'tbiethman/UNIFY-1816-prototype', << pipeline.git.branch >> ] + - equal: [ 'global-mode-issue', << pipeline.git.branch >> ] - matches: pattern: "-release$" value: << pipeline.git.branch >> @@ -46,7 +45,6 @@ linuxArm64WorkflowFilters: &linux-arm64-workflow-filters when: or: - equal: [ develop, << pipeline.git.branch >> ] - - equal: [ linux-arm64, << pipeline.git.branch >> ] - matches: pattern: "-release$" value: << pipeline.git.branch >> @@ -65,7 +63,6 @@ windowsWorkflowFilters: &windows-workflow-filters when: or: - equal: [ develop, << pipeline.git.branch >> ] - - equal: [ linux-arm64, << pipeline.git.branch >> ] - matches: pattern: "-release$" value: << pipeline.git.branch >> @@ -129,7 +126,7 @@ commands: - run: name: Check current branch to persist artifacts command: | - if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "tbiethman/UNIFY-1816-prototype" ]]; then + if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "global-mode-issue" ]]; then echo "Not uploading artifacts or posting install comment for this branch." circleci-agent step halt fi @@ -658,7 +655,7 @@ commands: ## by default, assert that at least 1 test ran default: 0 steps: - - run: + - run: name: 'Verify Mocha Results' command: | source ./scripts/ensure-node.sh @@ -1614,7 +1611,7 @@ jobs: path: /tmp/cypress - store_artifacts: path: /tmp/artifacts - - store-npm-logs + - store-npm-logs run-vite-dev-server-integration-tests: <<: *defaults @@ -1636,7 +1633,7 @@ jobs: path: /tmp/cypress - store_artifacts: path: /tmp/artifacts - - store-npm-logs + - store-npm-logs ui-components-integration-tests: <<: *defaults @@ -2363,7 +2360,7 @@ linux-x64-workflow: &linux-x64-workflow - run-vite-dev-server-integration-tests: context: [test-runner:cypress-record-key, test-runner:percy] requires: - - system-tests-node-modules-install + - system-tests-node-modules-install - run-app-component-tests-chrome: context: [test-runner:cypress-record-key, test-runner:launchpad-tests, test-runner:percy] percy: true diff --git a/cli/lib/exec/open.js b/cli/lib/exec/open.js index 777eed730f46..c77fdc639900 100644 --- a/cli/lib/exec/open.js +++ b/cli/lib/exec/open.js @@ -15,6 +15,12 @@ const { exitWithError } = require('../errors') * @returns {string[]} list of CLI arguments */ const processOpenOptions = (options = {}) => { + // In addition to setting the project directory, setting the project option + // here ultimately decides whether cypress is run in global mode or not. + // It's first based off whether it's installed globally by npm/yarn (-g). + // A global install can be overridden by the --project flag, putting Cypress + // in project mode. A non-global install can be overridden by the --global + // flag, putting it in global mode. if (!util.isInstalledGlobally() && !options.global && !options.project) { options.project = process.cwd() } diff --git a/packages/frontend-shared/cypress/e2e/e2ePluginSetup.ts b/packages/frontend-shared/cypress/e2e/e2ePluginSetup.ts index e883f643cb64..c6b7285f75fe 100644 --- a/packages/frontend-shared/cypress/e2e/e2ePluginSetup.ts +++ b/packages/frontend-shared/cypress/e2e/e2ePluginSetup.ts @@ -1,7 +1,7 @@ import path from 'path' import execa from 'execa' -import type { CyTaskResult, RemoteGraphQLInterceptor, ResetOptionsResult, WithCtxInjected, WithCtxOptions } from './support/e2eSupport' +import type { CyTaskResult, OpenGlobalModeOptions, RemoteGraphQLInterceptor, ResetOptionsResult, WithCtxInjected, WithCtxOptions } from './support/e2eSupport' import { fixtureDirs } from '@tooling/system-tests' // import type { CloudExecuteRemote } from '@packages/data-context/src/sources' import { makeGraphQLServer } from '@packages/graphql/src/makeGraphQLServer' @@ -86,6 +86,7 @@ async function makeE2ETasks () { const { scaffoldCommonNodeModules, scaffoldProjectNodeModules } = require('@tooling/system-tests/lib/dep-installer') const cli = require('../../../../cli/lib/cli') + const cliUtil = require('../../../../cli/lib/util') const cliOpen = require('../../../../cli/lib/exec/open') // Remove all the fixtures when the plugin starts @@ -288,12 +289,18 @@ async function makeE2ETasks () { return Fixtures.projectPath(opts.projectName) }, __internal_scaffoldProject, - async __internal_openGlobal (argv: string[] = []): Promise { - const openArgv = ['--global', ...argv] + async __internal_openGlobal ({ argv = [], byFlag = true }: OpenGlobalModeOptions): Promise { + let isInstalledGloballyStub + + if (byFlag) { + argv.unshift('--global') + } else { + isInstalledGloballyStub = sinon.stub(cliUtil, 'isInstalledGlobally').returns(true) + } // Runs the launchArgs through the whole pipeline for the CLI open process, // which probably needs a bit of refactoring / consolidating - const cliOptions = await cli.parseOpenCommand(['open', ...openArgv]) + const cliOptions = await cli.parseOpenCommand(['open', ...argv]) const processedArgv = cliOpen.processOpenOptions(cliOptions) const modeOptions = { ...argUtils.toObject(processedArgv), invokedFromCli: true } @@ -303,6 +310,8 @@ async function makeE2ETasks () { // Handle any pre-loading that should occur based on the launch arg settings await ctx.initializeMode() + isInstalledGloballyStub?.restore() + return { modeOptions, e2eServerPort: ctx.appServerPort, diff --git a/packages/frontend-shared/cypress/e2e/support/e2eSupport.ts b/packages/frontend-shared/cypress/e2e/support/e2eSupport.ts index c94b1c6bf81b..d5fb5dfd0f72 100644 --- a/packages/frontend-shared/cypress/e2e/support/e2eSupport.ts +++ b/packages/frontend-shared/cypress/e2e/support/e2eSupport.ts @@ -198,9 +198,14 @@ export interface ResetOptionsResult { e2eServerPort?: number | null } -function openGlobalMode (argv?: string[]) { +export interface OpenGlobalModeOptions { + argv?: string[] + byFlag?: boolean +} + +function openGlobalMode (options: OpenGlobalModeOptions = {}) { return logInternal({ name: 'openGlobalMode', message: '' }, () => { - return taskInternal('__internal_openGlobal', argv) + return taskInternal('__internal_openGlobal', options) }).then((obj) => { Cypress.env('e2e_serverPort', obj.e2eServerPort) diff --git a/packages/graphql/schemas/schema.graphql b/packages/graphql/schemas/schema.graphql index a7e475655fa0..219444950c20 100644 --- a/packages/graphql/schemas/schema.graphql +++ b/packages/graphql/schemas/schema.graphql @@ -1442,7 +1442,9 @@ type Query { """ invokedFromCli: Boolean! - """Whether the app is in global mode or not""" + """ + Whether the app is in global mode or not. This is based off the presence of a project, which is set by the CLI (or absent if the app is run directly). See cli/lib/exec/open.js for the logic that sets the project or not. + """ isGlobalMode: Boolean! """local settings on a device-by-device basis""" diff --git a/packages/graphql/src/schemaTypes/objectTypes/gql-Query.ts b/packages/graphql/src/schemaTypes/objectTypes/gql-Query.ts index e4f637dc3058..71da5316c788 100644 --- a/packages/graphql/src/schemaTypes/objectTypes/gql-Query.ts +++ b/packages/graphql/src/schemaTypes/objectTypes/gql-Query.ts @@ -78,8 +78,8 @@ export const Query = objectType({ }) t.nonNull.boolean('isGlobalMode', { - description: 'Whether the app is in global mode or not', - resolve: (source, args, ctx) => Boolean(ctx.modeOptions.global), + description: 'Whether the app is in global mode or not. This is based off the presence of a project, which is set by the CLI (or absent if the app is run directly). See cli/lib/exec/open.js for the logic that sets the project or not.', + resolve: (source, args, ctx) => !ctx.modeOptions.project, }) t.nonNull.field('authState', { diff --git a/packages/launchpad/cypress/e2e/global-mode.cy.ts b/packages/launchpad/cypress/e2e/global-mode.cy.ts index 83549e8affab..ce4251ffecc5 100644 --- a/packages/launchpad/cypress/e2e/global-mode.cy.ts +++ b/packages/launchpad/cypress/e2e/global-mode.cy.ts @@ -6,6 +6,20 @@ import { getPathForPlatform } from './support/getPathForPlatform' const sep = Cypress.platform === 'win32' ? '\\' : '/' describe('Launchpad: Global Mode', () => { + describe('methods of opening global mode', () => { + it('shows global page when opened by --global flag', () => { + cy.openGlobalMode() + cy.visitLaunchpad() + cy.get('h1').should('contain', defaultMessages.globalPage.empty.title) + }) + + it('shows global page when opened by global install', () => { + cy.openGlobalMode({ byFlag: false }) + cy.visitLaunchpad() + cy.get('h1').should('contain', defaultMessages.globalPage.empty.title) + }) + }) + describe('when no projects have been added', () => { it('shows "Add Project" view', () => { cy.openGlobalMode() @@ -71,7 +85,7 @@ describe('Launchpad: Global Mode', () => { describe('when projects have been added', () => { const setupAndValidateProjectsList = (projectList, globalModeOptions?: string[] | undefined) => { - cy.openGlobalMode(globalModeOptions) + cy.openGlobalMode({ argv: globalModeOptions }) // Adding a project puts the project first in the list, so we reverse the list // to ensure the projectList in the UI matches what is passed in.