diff --git a/.github/workflows/deployment.yaml b/.github/workflows/deployment.yaml new file mode 100644 index 00000000000..441f35e7167 --- /dev/null +++ b/.github/workflows/deployment.yaml @@ -0,0 +1,71 @@ +name: Deployment Tests +on: + workflow_dispatch: + inputs: + target: + description: 'Galaxy Deployment to target' + required: true + default: 'usegalaxymain' + type: choice + options: + - usegalaxytest + - usegalaxymain + - usegalaxyeu + type: + description: 'Test type' + required: true + default: 'all' + type: choice + options: + - all + - api + - selenium + branch: + description: 'Branch of code to run from' + default: 'dev' + type: string + debug: + required: true + description: 'Run deployment tests with debug mode on' + type: boolean +jobs: + testdeployment: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.7'] + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ inputs.branch }} + fetch-depth: 0 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Cache pip dir + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: pip-cache-${{ matrix.python-version }}-${{ hashFiles('requirements.txt') }} + - uses: nanasess/setup-chromedriver@v1 + - name: Run tests + run: bash ./test/deployment/usegalaxystar.bash + env: + GALAXY_TEST_DEPLOYMENT_TARGET: ${{ inputs.target }} + GALAXY_TEST_DEPLOYMENT_DEBUG: ${{ inputs.debug }} + GALAXY_TEST_DEPLOYMENT_TEST_TYPE: ${{ inputs.type }} + GALAXY_TEST_USEGALAXYMAIN_USER_EMAIL: "jmchilton+test@gmail.com" + GALAXY_TEST_USEGALAXYMAIN_USER_PASSWORD: ${{ secrets.USEGALAXYMAIN_USER_PASSWORD }} + GALAXY_TEST_USEGALAXYMAIN_USER_KEY: ${{ secrets.USEGALAXYMAIN_USER_KEY }} + GALAXY_TEST_USEGALAXYTEST_USER_EMAIL: "jmchilton+test@gmail.com" + GALAXY_TEST_USEGALAXYTEST_USER_PASSWORD: ${{ secrets.USEGALAXYTEST_USER_PASSWORD }} + GALAXY_TEST_USEGALAXYTEST_USER_KEY: ${{ secrets.USEGALAXYTEST_USER_KEY }} + GALAXY_TEST_USEGALAXYEU_USER_EMAIL: "jmchilton+test@gmail.com" + GALAXY_TEST_USEGALAXYEU_USER_PASSWORD: ${{ secrets.USEGALAXYEU_USER_PASSWORD }} + GALAXY_TEST_USEGALAXYEU_USER_KEY: ${{ secrets.USEGALAXYEU_USER_KEY }} + GALAXY_TEST_TIMEOUT_MULTIPLIER: 10 + - uses: actions/upload-artifact@v2 + if: always() + with: + name: Deployment test results (${{ inputs.target }}, ${{ inputs.type }}) + path: 'deployment_tests.html' diff --git a/.github/workflows/maintenance_bot.yaml b/.github/workflows/maintenance_bot.yaml index e8e78c8d60d..aca4415ff55 100644 --- a/.github/workflows/maintenance_bot.yaml +++ b/.github/workflows/maintenance_bot.yaml @@ -8,7 +8,7 @@ jobs: if: github.repository_owner == 'galaxyproject' runs-on: ubuntu-latest env: - MILESTONE_NUMBER: 23 + MILESTONE_NUMBER: 24 steps: - name: Get latest pull request labels id: get_pr_labels diff --git a/.vscode/.test.env b/.vscode/.test.env index 0fd4d77f2ed..8321bcadf92 100644 --- a/.vscode/.test.env +++ b/.vscode/.test.env @@ -1 +1 @@ -GALAXY_TEST_TOOL_CONF="lib/galaxy/config/sample/tool_conf.xml.sample,test/functional/tools/samples_tool_conf.xml" \ No newline at end of file +GALAXY_TEST_TOOL_CONF="lib/galaxy/config/sample/tool_conf.xml.sample,test/functional/tools/sample_tool_conf.xml" diff --git a/.vscode/launch_gitpod.json b/.vscode/launch_gitpod.json index c9bee582dcd..ebab8a9437a 100644 --- a/.vscode/launch_gitpod.json +++ b/.vscode/launch_gitpod.json @@ -10,7 +10,7 @@ "env": { "GALAXY_CONFIG_FILE": "${workspaceFolder}/config/galaxy.yml", "GALAXY_CONDA_AUTO_INIT": "false", - "GALAXY_CONFIG_TOOL_CONFIG_FILE": "lib/galaxy/config/sample/tool_conf.xml.sample,test/functional/tools/samples_tool_conf.xml", + "GALAXY_CONFIG_TOOL_CONFIG_FILE": "lib/galaxy/config/sample/tool_conf.xml.sample,test/functional/tools/sample_tool_conf.xml", "GALAXY_CONFIG_DATABASE_CONNECTION": "postgresql://localhost/galaxy" } }, diff --git a/Makefile b/Makefile index d2748e0ff5d..8821c7445e1 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VENV?=.venv # Source virtualenv to execute command (darker, sphinx, twine, etc...) IN_VENV=if [ -f "$(VENV)/bin/activate" ]; then . "$(VENV)/bin/activate"; fi; -RELEASE_CURR:=23.0 +RELEASE_CURR:=23.1 RELEASE_UPSTREAM:=upstream CONFIG_MANAGE=$(IN_VENV) python lib/galaxy/config/config_manage.py PROJECT_URL?=https://github.com/galaxyproject/galaxy @@ -162,6 +162,14 @@ skip-client: ## Run only the server, skipping the client build. GALAXY_SKIP_CLIENT_BUILD=1 sh run.sh node-deps: ## Install NodeJS dependencies. +ifndef YARN + @echo "Could not find yarn, which is required to install the Galaxy client.\nTo install yarn, please visit \033[0;34mhttps://yarnpkg.com/en/docs/install\033[0m for instructions, and package information for all platforms.\n" + false; +else + yarn install $(YARN_INSTALL_OPTS) +endif + +client-node-deps: ## Install NodeJS dependencies for the client. ifndef YARN @echo "Could not find yarn, which is required to build the Galaxy client.\nTo install yarn, please visit \033[0;34mhttps://yarnpkg.com/en/docs/install\033[0m for instructions, and package information for all platforms.\n" false; @@ -176,7 +184,7 @@ build-api-schema: remove-api-schema: rm _schema.yaml -update-client-api-schema: node-deps build-api-schema +update-client-api-schema: client-node-deps build-api-schema $(IN_VENV) cd client && node openapi_to_schema.mjs ../_schema.yaml > src/schema/schema.ts && npx prettier --write src/schema/schema.ts $(MAKE) remove-api-schema @@ -185,34 +193,34 @@ lint-api-schema: build-api-schema $(IN_VENV) codespell -I .ci/ignore-spelling.txt _schema.yaml $(MAKE) remove-api-schema -client: node-deps ## Rebuild client-side artifacts for local development. +install-client: node-deps ## Install prebuilt client as defined in root package.json + yarn install && yarn run stage + +client: client-node-deps ## Rebuild client-side artifacts for local development. cd client && yarn run build -client-production: node-deps ## Rebuild client-side artifacts for a production deployment without sourcemaps. +client-production: client-node-deps ## Rebuild client-side artifacts for a production deployment without sourcemaps. cd client && yarn run build-production -client-production-maps: node-deps ## Rebuild client-side artifacts for a production deployment with sourcemaps. +client-production-maps: client-node-deps ## Rebuild client-side artifacts for a production deployment with sourcemaps. cd client && yarn run build-production-maps -client-format: node-deps ## Reformat client code +client-format: client-node-deps ## Reformat client code cd client && yarn run format -client-watch: node-deps ## A useful target for parallel development building. See also client-dev-server. - cd client && yarn run watch +client-dev-server: client-node-deps ## Starts a webpack dev server for client development (HMR enabled) + cd client && yarn run develop -client-dev-server: node-deps ## Starts a webpack dev server for client development (HMR enabled) - cd client && yarn run serve - -client-test: node-deps ## Run JS unit tests +client-test: client-node-deps ## Run JS unit tests cd client && yarn run test -client-eslint-precommit: node-deps # Client linting for pre-commit hook; skips glob input and takes specific paths +client-eslint-precommit: client-node-deps # Client linting for pre-commit hook; skips glob input and takes specific paths cd client && yarn run eslint-precommit -client-eslint: node-deps # Run client linting +client-eslint: client-node-deps # Run client linting cd client && yarn run eslint -client-format-check: node-deps # Run client formatting check +client-format-check: client-node-deps # Run client formatting check cd client && yarn run format-check client-lint: client-eslint client-format-check ## ES lint and check format of client diff --git a/client/.eslintrc.json b/client/.eslintrc.json index f13b7808484..a02efdbb365 100644 --- a/client/.eslintrc.json +++ b/client/.eslintrc.json @@ -59,7 +59,7 @@ "vuejs-accessibility/no-autofocus": "error", "vuejs-accessibility/tabindex-no-positive": "error" }, - "ignorePatterns": ["src/qunit", "src/mocha", "src/libs", "src/nls", "src/legacy"], + "ignorePatterns": ["dist", "src/qunit", "src/mocha", "src/libs", "src/nls", "src/legacy"], "overrides": [ { "files": ["**/*.vue"], diff --git a/client/.prettierignore b/client/.prettierignore new file mode 100644 index 00000000000..143859dcc25 --- /dev/null +++ b/client/.prettierignore @@ -0,0 +1,14 @@ +# Standard ignores +**/.git +**/.svn +**/.hg +**/node_modules +# Ignore the dist folder +**/dist +# We will always defer to package manager for formatting of package.json files. +**/package.json +# Skip formatting of explicitly included libs (to stay in sync with upstream, and they should go away eventually) +src/libs +# Don't reformat .json or .yml files included in the project +*.json +*.yml diff --git a/client/README.md b/client/README.md index 15fad423884..abb2741ce1b 100644 --- a/client/README.md +++ b/client/README.md @@ -1,19 +1,19 @@ # Client Build System Installs, stages, and builds the client-side scripts necessary for running the -Galaxy webapp. When started through `run.sh` or any other method that utilizes -`scripts/common_startup.sh`, Galaxy will (since 18.09) _automatically_ build -the client as a part of server startup, when it detects changes, unless that +Galaxy web client. When started through `run.sh` or any other method that +utilizes `scripts/common_startup.sh`, Galaxy will (since 18.09) _automatically_ +build the client as a part of server startup when it detects changes unless that functionality is explicitly disabled. -The base dependencies used are Node.js and Yarn. Galaxy now includes these in -the virtual environment, and they can be accessed by activating that with `. -.venv/bin/activate` from the Galaxy root directory. +The base dependencies used are Node.js and Yarn. Galaxy includes appropriate +versions of these in the virtual environment, and they can be accessed by +activating that with `. .venv/bin/activate` from the Galaxy root directory. -If you'd like to install your own dependencies, on OSX the easiest way to get -set up is using `homebrew` and the command `brew install nodejs yarn`. More -information, including instructions for other platforms, is available at -[https://nodejs.org](https://nodejs.org) and +If you'd like to install your dependencies external to Galaxy, on OSX the +easiest way to get set up is using `homebrew` and the command `brew install +nodejs yarn`. More information, including instructions for other platforms, is +available at [https://nodejs.org](https://nodejs.org) and [https://yarnpkg.com/](https://yarnpkg.com). The Galaxy client build has necessarily grown more complex in the past several @@ -27,11 +27,11 @@ directly on Gitter at There are many moving parts to the client build system, but the entry point for most people is the 'client' rule in the Makefile at the root of the Galaxy -repository. Execute the following to perform a complete build suitable for -local development, including dependency staging, style building, script -processing, and bundling. This is a development-specific build which includes -extra debugging features, and excludes several production optimizations made -during the build process. +repository. Execute the following to perform a complete build suitable for local +development, including dependency staging, style building, script processing, +and bundling. This is a development-specific build that includes extra debugging +features and excludes several production optimizations made during the build +process. make client @@ -53,39 +53,31 @@ and these should not be committed. When you're actively developing, it is convenient to have the client automatically rebuild every time you save a file. You can do this using: - make client-watch - -This will first stage client dependencies, initiate a build, and then will -watch for changes in any of the galaxy client source files. When a file is -changed, the client will automatically rebuild, after which you can refresh -your browser to see changes. - -For even more rapid development you can use the webpack development server, -which takes advantage of hot module replacement (HMR). This technique allows -swapping out of javascript modules while the application is running without -requiring a full page reload most of the time, at least in the more modern -parts of the application. - -The command below starts a special webpack dev server after a client -build. - make client-dev-server -This will start up an extra client development server running on port 8081. -Open your browser to http://localhost:8081 (instead of the default 8080 that -Galaxy would run on), and you should see Galaxy like normal. Except now, when -you change client code it'll automatically rebuild *and* reload the relevant -portion of the application for you. Lastly, if you -are running Galaxy at a location other than the default, you can specify a -different proxy target (in this example, port 8000) using the GALAXY_URL -environment variable: +Or, with the package scripts from this `client` directory: + + yarn run develop + +This will start up an extra client development server running on port 8081. Open +your browser to `http://localhost:8081` (instead of the default 8080 that Galaxy +would run on), and you should see Galaxy like normal. Except now, when you +change client code it'll automatically rebuild _and_ reload the relevant portion +of the application for you. Lastly, if you are running Galaxy at a location +other than the default, you can specify a different proxy target (in this +example, port 8000) using the GALAXY_URL environment variable: GALAXY_URL="http://localhost:8000" make client-dev-server -Sometimes you want to run your local UI against a remote Galaxy server. This is also possible, if you enable `CHANGE_ORIGIN` flag +Sometimes you want to run your local UI against a remote Galaxy server. This is +also possible if you set the `CHANGE_ORIGIN` environment variable: CHANGE_ORIGIN=true GALAXY_URL="https://usegalaxy.org/" make client-dev-server +You can also specify a particular port to bind the dev server to: + + WEBPACK_PORT=8083 yarn run develop + ## Running a Separate Server When developing the client it can be helpful to run a local server for the @@ -94,17 +86,22 @@ commands. This command will run galaxy without building the client: make skip-client +Or by setting the following environment variable and running Galaxy however you +prefer: + + GALAXY_SKIP_CLIENT_BUILD=1 ./run.sh + ## Changing Styles/CSS -Galaxy uses Sass for its styling, which is a superset of CSS that compiles down -to regular CSS. Most Galaxy styling source (.scss) files are kept in -`client/src/style/scss`. There are additionally style blocks alongside some Vue -components -- styles that are particular to that individual component and do -not apply site-wide. +Galaxy uses Sass for globally applied styling, which is a superset of CSS that +compiles down to regular CSS. Most Galaxy styling source (.scss) files are kept +in `client/src/style/scss`. Many components will also have local style blocks +containing styles that are particular to that individual component and do not +apply site-wide. On build, the compiled css bundle is served at `/static/style/base.css`. -As mentioned above, `make client` will rebuild styles, as a part of the webpack +As mentioned above, `make client` will rebuild styles as a part of the webpack build. For iterative development, "Watch Mode" rebuilds as described above do include style changes. @@ -122,7 +119,7 @@ framework. For testing Vue components, we use the [Vue testing utils](https://vue-test-utils.vuejs.org/) to mount individual components in a -test bed and check them for rendered features. Please use jest-based mocking +test bed and check them for rendered features. Please use jest-based mocking for isolating test functionality. A set of older qUnit tests also exist which will be phased-out as the code they @@ -142,8 +139,8 @@ directory. This is what happens during a complete client build. During client-side development, it is more convenient to have granular testing options. The various testing scripts are defined inside package.json within the -client folder, and are called with `yarn` as demonstrated in the -following commands. +client folder and are called with `yarn` as demonstrated in the following +commands. This is what CI is going to run, and also what 'make client-test' invokes, executing all the client tests: @@ -154,7 +151,7 @@ You can also bypass qunit and single-run all of the jest tests like so: yarn run jest -Or, if you really want to run just the qunit tests: +Or, if you want to run just the qunit tests: yarn run qunit diff --git a/client/docs/avoid-using-global-Galaxy.md b/client/docs/avoid-using-global-Galaxy.md index 2a19a2597c7..3092190ce58 100644 --- a/client/docs/avoid-using-global-Galaxy.md +++ b/client/docs/avoid-using-global-Galaxy.md @@ -9,17 +9,17 @@ you access to the Galaxy.config, current user, and current user histories. Pleas retrieve your values, and bypass importing Galaxy altogether. #### Sometimes you still need to update Vue from backbone as the legacy environment changes + There are definitely use-cases where the Backbone models update over time and we need to update some value inside Vue. Instead of importing backbone models directly into Vue components, try building a backbone event listener that updates some relevant Vuex store. -* [Keeping Vuex in Sync with - Galaxy](https://github.com/galaxyproject/galaxy/blob/dev/client/src/store/syncVuexToGalaxy.js) +- [Keeping Vuex in Sync with + Galaxy](https://github.com/galaxyproject/galaxy/blob/dev/client/src/store/syncVuexToGalaxy.js) These issues should disappear over time as the all of the old client is rebuilt in the new ecosystem. - ## Mount Functions In what most people think of as a "standard" Vue application there would be only one place that Vue @@ -30,7 +30,6 @@ However, we are incrementally replacing old Backbone views, so in its current st several mounting functions for various components depending on where that component is intended to fit into the existing Backbone layouts. - ### Using the standard mount to pass in Galaxy variables as props A standard mount function has been provided in src/utils. This mount function accepts a component @@ -46,28 +45,26 @@ import MyComponent from "components/MyComponent"; import { mountVueComponent } from "utils/mountVueComponent"; const OldBackboneView = { - someInitMethodYouMake() { const Galaxy = getGalaxyInstance(); const mounter = mountVueComponent(MyComponent); // pass in required props - const props = { - + const props = { // Something peeled off the global galaxy - somePropVal: Galaxy.someDealie, + somePropVal: Galaxy.someDealie, // ...or the current history name: Galaxy.currentHistory.name, // or maybe from the backbone model for this view - shoeSize: this.model.shoeSize + shoeSize: this.model.shoeSize, }; // VM is a Vue instance. // this.$el is some jquery selection, first item is the actual DOM object const container = this.$el[0]; const vm = mounter(props, container); - } -} + }, +}; ``` diff --git a/client/docs/composables.md b/client/docs/composables.md index a7a22b5c6d3..248e30f5575 100644 --- a/client/docs/composables.md +++ b/client/docs/composables.md @@ -6,9 +6,9 @@ Using them effectively can make your code more reusable, decoupled, and easier t **More about Composables:** -* [Composables Overview](https://vuejs.org/guide/reusability/composables.html) -* [Composition API](https://vuejs.org/api/composition-api-setup.html) -* [\ ``` @@ -79,7 +79,7 @@ import { useCurrentUser } from "composables/user"; jest.mock("composables/user"); useCurrentUser.mockReturnValue({ - currentUser: {} + currentUser: {}, }); ``` @@ -95,11 +95,7 @@ Usage: ``` diff --git a/client/docs/headings.md b/client/docs/headings.md index a7cf82bfb14..87538b3d8a6 100644 --- a/client/docs/headings.md +++ b/client/docs/headings.md @@ -6,23 +6,23 @@ Heading Levels are used by screen readers, and other software, to get a rough id ## Heading Level best practices - - Make sure every route has exactly one `

` element, which best describes the content of the current page. +- Make sure every route has exactly one `

` element, which best describes the content of the current page. - - When increasing a heading level, do not skip Levels. +- When increasing a heading level, do not skip Levels. - - Do not use a headings level to determine it's size. Use one of the heading utility classes (e.g. `h-lg`) instead. +- Do not use a headings level to determine it's size. Use one of the heading utility classes (e.g. `h-lg`) instead. - - Do not use a heading tag to make a non-heading text large. Use a heading utility class on a `` instead. +- Do not use a heading tag to make a non-heading text large. Use a heading utility class on a `` instead. ## Sizing Headings There are several utility classes which size headings: - - `h-xl` - Extra large headings - - `h-lg` - Large headings (most main headings should have this size) - - `h-md` - Medium headings - - `h-sm` - Small headings (many sub-headings have this size) - - `h-text` - Text sized headings +- `h-xl` - Extra large headings +- `h-lg` - Large headings (most main headings should have this size) +- `h-md` - Medium headings +- `h-sm` - Small headings (many sub-headings have this size) +- `h-text` - Text sized headings Galaxy uses `h-lg` for most top-level (`

`) headings. @@ -45,8 +45,8 @@ Set the headings level, by setting aa `h1 ... h6` prop: Following properties allow for further styling the component: - - `size=["xl", "lg", "md", "sm", "text"]` - sets the headings size class - - `bold` - makes a heading bold - - `inline` - displays the heading inline - - `separator` - draws a separating line, to better distinguish sections - - `icon="..."` - adds a font-awesome icon decoration to the left of the heading. Make sure to also load the icon with `library.add(...)`. +- `size=["xl", "lg", "md", "sm", "text"]` - sets the headings size class +- `bold` - makes a heading bold +- `inline` - displays the heading inline +- `separator` - draws a separating line, to better distinguish sections +- `icon="..."` - adds a font-awesome icon decoration to the left of the heading. Make sure to also load the icon with `library.add(...)`. diff --git a/client/docs/never-use-jquery.md b/client/docs/never-use-jquery.md index c1e07181928..df7a5370da5 100644 --- a/client/docs/never-use-jquery.md +++ b/client/docs/never-use-jquery.md @@ -1,6 +1,6 @@ Did you know, jQuery is old enough to drive? It's old enough to get a driver's license. jQuery is a tool that was built to deal with inconsistencies in browsers that NO LONGER EXIST. In a couple -years, jQuery will be voting, drinking, and capable of being tried as an adult. +years, jQuery will be voting, drinking, and capable of being tried as an adult. If you think you need jQuery, you are mistaken. Please seek help from somebody in the wg-ui-ux workgroup. There is nothing jQuery can provide you that isn't already part of vanilla javascript or @@ -14,5 +14,6 @@ One of our most important goals in redesigning Galaxy is the complete eliminatio from our source, along with all its invasive plugins. ### References -* [You Don't Need jQuery](https://github.com/nefe/You-Dont-Need-jQuery) -* [document.querySelector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) \ No newline at end of file + +- [You Don't Need jQuery](https://github.com/nefe/You-Dont-Need-jQuery) +- [document.querySelector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) diff --git a/client/docs/providers-and-renderers.md b/client/docs/providers-and-renderers.md index 1eca93b3e13..2637fcbf9f9 100644 --- a/client/docs/providers-and-renderers.md +++ b/client/docs/providers-and-renderers.md @@ -22,34 +22,27 @@ component we previously made, but you are free to putput whatever you want in th doodad and saveDoddad properties as desired, as well as any other local data with the only restriction that Vue needs a single root element in which to render. - ## The Renderer ```html static ``` @@ -66,7 +59,6 @@ binds](https://vuejs.org/v2/guide/components-custom-events.html#sync-Modifier)). Whatever happens to that new object is somebody else's job. As soon as you tie the data management to the rendering, the re-usability of your components craters. - ## The Provider As the opposite of the rendering component, a provider or renderless component, is pure logic. It @@ -76,7 +68,6 @@ functionality available in Vue. Some others are [Mixins](https://vuejs.org/v2/gu [Provide/Inject](https://v3.vuejs.org/guide/component-provide-inject.html) and (in Vue3) [the composition API](https://v3.vuejs.org/guide/composition-api-introduction.html). - ```js static // DoodadProvider.js @@ -134,7 +125,7 @@ mandatory markup, just one big empty slot. // Testing a renderless component import { shallowMount } from "@vue/test-utils"; -import { getLocalVue, waitForLifecyleEvent } from "tests/jest/helpers" +import { getLocalVue, waitForLifecyleEvent } from "tests/jest/helpers"; import DoodadProvider from "./DoodadProvider"; describe("A renderless component", () => { @@ -157,12 +148,12 @@ describe("A renderless component", () => { // component. This is often good enough for waiting for // an initial ajax load to finish, for example await waitForLifecyleEvent(wrapper.vm, "updated"); - }) + }); test("someProp", () => { const { someProp } = slotProps; expect(someProp).toExist(); // ...more tests - }) -}) + }); +}); ``` diff --git a/client/docs/readme.md b/client/docs/readme.md index dba0f97c1e1..e7442b5637b 100644 --- a/client/docs/readme.md +++ b/client/docs/readme.md @@ -5,7 +5,7 @@ I'm not talking about how webpack turns it into a rendering function. That's obv I mean conceptually, props come in (like arguments) and events go out (like the return statements). A component is a fancy kind of function that can keep emitting results and accept changing inputs over time. In truth it more closely resembles an Observable, but an observable is ALSO a slightly -fancier kind of function. +fancier kind of function. If you just think of a component as thing that takes input props and emits output events you're well on your way to using them well. @@ -19,22 +19,22 @@ problems of the old imperative class-based legacy code. New vue programmers are ok at handing props to components, but they rarely use events effectively (at first). As a result they end up using a lot of global state, a million little data props and relying on imperfect globalized tools like Vuex or other imported dependencies for every little -variable. +variable. Vuex definitely has its uses, but not as many as you might expect given the way it is overly-emphasized in common tutorials. It's easy to walk away from an "Intro to Vue" video with the -idea that all data must live in Vuex all the time. That's a really undesirable situation. +idea that all data must live in Vuex all the time. That's a really undesirable situation. Although vuex is a well-organized (many would say over-organized) state machine, it is important to remember that it is still a kind of global injection and deserves to be considered as such. -* [Should I Store This Data in - Vuex](https://markus.oberlehner.net/blog/should-i-store-this-data-in-vuex/) -* [Vuex getters are great, but don’t overuse - them](https://codeburst.io/vuex-getters-are-great-but-dont-overuse-them-9c946689b414) +- [Should I Store This Data in + Vuex](https://markus.oberlehner.net/blog/should-i-store-this-data-in-vuex/) +- [Vuex getters are great, but don’t overuse + them](https://codeburst.io/vuex-getters-are-great-but-dont-overuse-them-9c946689b414) Data persistence should be something that happens near the top of your component tree, not down in -the guts. +the guts. Your first thought with a component should be: "How can I offload the handling of the results of this component to my caller?" The answer is usually going to be events. A component that simply @@ -46,7 +46,6 @@ global state to operate. They're just fancy shorthands for a prop / event handler combination. They are fundamentally no different from props and events, but the syntax is important to understand. - ### Think carefully about what should really be in "data". Most of good component design boils down to answering the following question: What do I want to put diff --git a/client/docs/styleguide.md b/client/docs/styleguide.md index 938ed22fc23..d158fd0a3a3 100644 --- a/client/docs/styleguide.md +++ b/client/docs/styleguide.md @@ -44,7 +44,7 @@ const myFunction = (param) => { }; // anonymous functions -const myFunction = function(param) { +const myFunction = function (param) { //do stuff }; ``` @@ -84,10 +84,9 @@ When possible, use arrow functions instead. > export function myFunction(parameter) { > const addOne = (value) => { > return value + 1; -> } +> }; > // do more stuff... > } -> > ``` > > **Don't** @@ -96,12 +95,11 @@ When possible, use arrow functions instead. > // in myModules.js > > export const myFunction = (parameter) => { -> const addOne = function(value) { +> const addOne = function (value) { > return value + 1; -> } +> }; > // do more stuff... -> } -> +> }; > ``` ## HTML Multi-Line Layout @@ -115,9 +113,7 @@ Prettier tries to respect whitespace when formatting your HTML templates, even w Might get turned into: ```vue -A very Long Button Text +A very Long Button Text ``` Notice the strange positioning of the `>` brackets. @@ -277,7 +273,7 @@ Do not add space between elements connected by conditionals. > > condition met > -> +> > > condition not met > @@ -293,7 +289,7 @@ Add space between non-connected elements. > > First span. > -> +> > > Second span. > @@ -325,7 +321,7 @@ Add space between logical blocks of elements. > > condition 1 not met > -> +> > > condition 2 met > diff --git a/client/docs/unit-testing/debugging-unit-tests.md b/client/docs/unit-testing/debugging-unit-tests.md index d7916cf6fa5..74097ef365b 100644 --- a/client/docs/unit-testing/debugging-unit-tests.md +++ b/client/docs/unit-testing/debugging-unit-tests.md @@ -9,7 +9,7 @@ code updates its test extensions again. #### To debug a single Jest test: -1. Open a jest test (a file that ends with *.test.js) +1. Open a jest test (a file that ends with \*.test.js) 1. Make sure the test file is selected, especially if you have multiple files open. This process will fail confusingly and without obvious error if you have not launched the debugger with the @@ -34,8 +34,6 @@ code updates its test extensions again. variables near your breakpoint and see their values in the "Variables" section of the Run and Debug pane. - - ```json // sample launch.json { @@ -45,16 +43,16 @@ code updates its test extensions again. "type": "node", "name": "debug selected jest test", "request": "launch", - + // launches version of jest from inside the node_modules // this means you need to have run yarn first "program": "${workspaceFolder}/client/node_modules/jest/bin/jest", "args": [ - // Alias -i. + // Alias -i. // Normally jest opens up a bunch of workers to run all your tests faster // but we don't want that right now. "--runInBand", - + // finds jest config "--config", "${workspaceFolder}/client/tests/jest/jest.config.js", @@ -68,9 +66,8 @@ code updates its test extensions again. "console": "integratedTerminal", // allows you to place breakpoints right in vscode's gutter - "disableOptimisticBPs": true, - }, - + "disableOptimisticBPs": true + } ] } ``` diff --git a/client/docs/unit-testing/readme.md b/client/docs/unit-testing/readme.md index 393c1a0c117..72c3ef2e582 100644 --- a/client/docs/unit-testing/readme.md +++ b/client/docs/unit-testing/readme.md @@ -1,20 +1,18 @@ - [Galaxy uses Jest](https://jestjs.io/) for its client-side unit testing framework. For testing Vue components, we use the [Vue testing utils](https://vue-test-utils.vuejs.org/) to mount individual components in a -test bed and check them for rendered features. Please use jest-based mocking +test bed and check them for rendered features. Please use jest-based mocking for isolating test functionality. - ### Specific test scenarios & examples -* [Mocking an imported -dependency](https://github.com/galaxyproject/galaxy/blob/dev/client/src/components/Tags/tagService.test.js) -* [Testing async -operations](https://github.com/galaxyproject/galaxy/blob/dev/client/src/components/Tags/tagService.test.js) -* [Testing a Vue component for expected rendering -output](https://github.com/galaxyproject/galaxy/blob/dev/client/src/components/Tags/StatelessTags.test.js) -* [Firing an event against a shallow mounted vue -component](https://github.com/galaxyproject/galaxy/blob/dev/client/src/components/Tags/StatelessTags.test.js) +- [Mocking an imported + dependency](https://github.com/galaxyproject/galaxy/blob/dev/client/src/components/Tags/tagService.test.js) +- [Testing async + operations](https://github.com/galaxyproject/galaxy/blob/dev/client/src/components/Tags/tagService.test.js) +- [Testing a Vue component for expected rendering + output](https://github.com/galaxyproject/galaxy/blob/dev/client/src/components/Tags/StatelessTags.test.js) +- [Firing an event against a shallow mounted vue + component](https://github.com/galaxyproject/galaxy/blob/dev/client/src/components/Tags/StatelessTags.test.js) diff --git a/client/docs/unit-testing/strategies.md b/client/docs/unit-testing/strategies.md index 64c343cc850..d06353193c3 100644 --- a/client/docs/unit-testing/strategies.md +++ b/client/docs/unit-testing/strategies.md @@ -1,4 +1,4 @@ -Part of making good code is making that code easy to test. +Part of making good code is making that code easy to test. ### Implement logic in pure functions when possible @@ -10,14 +10,13 @@ There is almost definitely no such thing as a well-written 1000 line function. Most of whatever happened in that thing was probably deterministic and can be broken up into easily testable chunks. - ### Wrap native browser resources in a function so they can be easily mocked If your javascript needs to talk to the window object, or navigator, etc. wrap that in a function call so that it can be easily mocked during testing. - #### Your Module + ```js static // myModule.js @@ -35,6 +34,7 @@ export function theThingYouReallyCareAbout() { ``` #### Your test file + ```js static // myModule.test.js import { theThingYouReallyCareAbout, redirectTo } from "./myModule"; diff --git a/client/docs/unit-testing/writing-tests.md b/client/docs/unit-testing/writing-tests.md index 8951b5797de..9a49db6c510 100644 --- a/client/docs/unit-testing/writing-tests.md +++ b/client/docs/unit-testing/writing-tests.md @@ -2,14 +2,13 @@ Please remember that these tests are not _for_ you. They're for the people who come after you. It will be a lot easier to modify, repair and upgrade your code -if they can figure out what you were originally hoping to accomplish. Try to +if they can figure out what you were originally hoping to accomplish. Try to use as detailed 'expect' statements as possible -- overuse of 'toBeTruthy()' for example, can hide the intent of your test. -Add a couple of comments. Use variable names that mean something. Nobody's +Add a couple of comments. Use variable names that mean something. Nobody's code is as self-documenting as they believe it to be. - ### Only test the public API that you define Internal implementations come and go with library upgrades and new tech. But @@ -20,17 +19,16 @@ Separate your concerns and identify the developer-facing methods and functions you expect them to use. Test THOSE. Everything else should probably be considered an implementation detail. -The other side of the same coin is to test *only* the unit in question. If your +The other side of the same coin is to test _only_ the unit in question. If your component has a model that uses a service that touches Vuex, which then uses -Axios to fetch some data -- don't test all that at once. Break things apart and -mock functionality to isolate testing to units. End to end testing is a +Axios to fetch some data -- don't test all that at once. Break things apart and +mock functionality to isolate testing to units. End to end testing is a separate thing that shouldn't be attempted using spec tests in Jest. Assume nobody cares _how_ your code works, we just need to know that the public API you designed _does_ work. If performance problems or new tech necessitate a re-write, these tests become a guide for the next implementation. - ### Writing a test file Jest will try to test any file ending in "\*.test.js". Please place your test @@ -65,9 +63,7 @@ describe("some module you wrote", () => { }); ``` - ### Check out the Jest helper functions We have created some [common helpers for common testing -scenarios](https://github.com/galaxyproject/galaxy/blob/dev/client/tests/jest/helpers.js). - +scenarios](https://github.com/galaxyproject/galaxy/blob/dev/client/tests/jest/helpers.js). diff --git a/client/package.json b/client/package.json index dbcf569c61f..6e3f76bfc7e 100644 --- a/client/package.json +++ b/client/package.json @@ -1,5 +1,5 @@ { - "name": "galaxy-client", + "name": "@galaxyproject/galaxy-client", "version": "0.1.0", "description": "Galaxy client application build system", "keywords": [ @@ -9,7 +9,10 @@ "type": "git", "url": "https://github.com/galaxyproject/galaxy.git" }, - "license": "AFL-3.0", + "license": "MIT", + "files": [ + "dist" + ], "browserslist": [ "defaults", "not ie <= 11", @@ -110,20 +113,18 @@ "xml-beautifier": "^0.5.0" }, "scripts": { - "watch": "gulp && yarn run save-build-hash && yarn run webpack-watch", - "serve": "NODE_OPTIONS=--max-old-space-size=4096 && NODE_ENV=development gulp && webpack serve", - "build": "NODE_ENV=development gulp && webpack && yarn run save-build-hash", - "build-production": "NODE_ENV=production gulp && yarn run webpack-production && yarn run save-build-hash", - "build-production-maps": "NODE_ENV=production gulp && yarn run webpack-production-maps && yarn run save-build-hash", + "develop": "NODE_OPTIONS=--max-old-space-size=4096 NODE_ENV=development gulp && webpack-dev-server", + "build": "NODE_ENV=development gulp && webpack && yarn run stage-build", + "build-production": "NODE_ENV=production gulp && yarn run webpack-production && yarn run stage-build", + "build-production-maps": "NODE_ENV=production gulp && yarn run webpack-production-maps && yarn run stage-build", "build-stats": "NODE_ENV=production webpack --profile --json=webpack-stats.json", "view-stats": "webpack-bundle-analyzer webpack-stats.json ../static/dist/", - "webpack-watch": "webpack --watch", "webpack-production": "NODE_ENV=production webpack", "webpack-production-maps": "GXY_BUILD_SOURCEMAPS=1 NODE_ENV=production webpack", "gulp": "gulp", - "save-build-hash": "(git rev-parse HEAD 2>/dev/null || echo '') >../static/client_build_hash.txt", - "format": "prettier --write 'src/style/scss/**/*.scss' 'src/**/{*.ts,*.js,*.vue}' 'tests/jest/standalone/{*.ts,*.js}' '!src/libs/**'", - "format-check": "prettier --check 'src/style/scss/**/*.scss' 'src/**/{*.js,*.vue}' 'tests/jest/standalone/{*.ts,*.js}' '!src/libs/**'", + "stage-build": "cpy 'dist/*' '../static/dist' && (git rev-parse HEAD 2>/dev/null || echo '') >../static/client_build_hash.txt", + "format": "prettier --write .", + "format-check": "prettier --check .", "prettier": "yarn run format", "test": "yarn run qunit && yarn run jest", "jest": "jest --config tests/jest/jest.config.js", @@ -151,6 +152,7 @@ "axios-mock-adapter": "^1.20.0", "babel-jest": "^29.3.1", "buffer": "^6.0.3", + "cpy-cli": "^4.2.0", "css-loader": "^6.7.1", "css-minimizer-webpack-plugin": "^4.0.0", "del": "^6.0.0", diff --git a/client/prettier.config.js b/client/prettier.config.js index df792433737..d9cc69f4d8c 100644 --- a/client/prettier.config.js +++ b/client/prettier.config.js @@ -1,5 +1,5 @@ module.exports = { tabWidth: 4, printWidth: 120, - bracketSameLine: true + bracketSameLine: true, }; diff --git a/client/src/components/Alert.md b/client/src/components/Alert.md index 021efd67e56..61038ebc71a 100644 --- a/client/src/components/Alert.md +++ b/client/src/components/Alert.md @@ -8,7 +8,7 @@ ```js
- A {{variant}} message + A {{ variant }} message
``` diff --git a/client/src/components/Dataset/DatasetName.vue b/client/src/components/Dataset/DatasetName.vue index 1625cd497ac..9751155ea3d 100644 --- a/client/src/components/Dataset/DatasetName.vue +++ b/client/src/components/Dataset/DatasetName.vue @@ -22,11 +22,11 @@ diff --git a/client/src/components/DatasetInformation/DatasetAttributes.vue b/client/src/components/DatasetInformation/DatasetAttributes.vue index dd942966dd0..73874c5f601 100644 --- a/client/src/components/DatasetInformation/DatasetAttributes.vue +++ b/client/src/components/DatasetInformation/DatasetAttributes.vue @@ -20,12 +20,16 @@ @click="submit('attribute', 'attributes')"> {{ "Save" | l }} - + {{ "Auto-detect" | l }} - +