From 970634282092f8495f587924dd28d98eb2c45cf1 Mon Sep 17 00:00:00 2001 From: Marine Dunstetter Date: Fri, 10 Nov 2023 15:51:56 +0100 Subject: [PATCH 1/2] feat: implement the catch up automation script --- package-lock.json | 29 +++++- package.json | 8 +- scripts/catchup.mjs | 236 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 267 insertions(+), 6 deletions(-) create mode 100644 scripts/catchup.mjs diff --git a/package-lock.json b/package-lock.json index 89f617ca5..0a8de3608 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "broccoli-asset-rev": "^3.0.0", "chai": "^4.3.4", "dictionary-fr": "^2.8.0", + "dotenv": "^16.3.1", "ember-auto-import": "^2.6.1", "ember-cli": "~3.28.6", "ember-cli-app-version": "^5.0.0", @@ -58,8 +59,9 @@ "loader.js": "^4.7.0", "lodash": "^4.17.21", "markdown-link-extractor": "^1.2.2", + "minimist-lite": "^2.2.1", "mocha": "^8.3.2", - "node-fetch": "^2.6.7", + "node-fetch": "^2.7.0", "npm-run-all": "^4.1.5", "prember": "^1.0.3", "prettier": "^2.5.1", @@ -77,6 +79,7 @@ "retext-spell": "^5.3.0", "retext-syntax-urls": "^3.1.2", "sass": "^1.62.1", + "shelljs": "^0.8.5", "unified": "^10.1.2", "walk-sync": "^2.0.2" }, @@ -11939,6 +11942,18 @@ "node": ">=8" } }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, "node_modules/duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -30459,6 +30474,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minimist-lite": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/minimist-lite/-/minimist-lite-2.2.1.tgz", + "integrity": "sha512-RSrWIRWGYoM2TDe102s7aIyeSipXMIXKb1fSHYx1tAbxAV0z4g2xR6ra3oPzkTqFb0EIUz1H3A/qvYYeDd+/qQ==", + "dev": true + }, "node_modules/minipass": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", @@ -31142,9 +31163,9 @@ "dev": true }, "node_modules/node-fetch": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.8.tgz", - "integrity": "sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, "dependencies": { "whatwg-url": "^5.0.0" diff --git a/package.json b/package.json index 4bfcd8d50..e6a4ba3f3 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,8 @@ "test:ember": "ember test", "test:node": "mocha node-tests --exclude node-tests/local/**", "test:node-local": "mocha node-tests/local", - "test:node-local-exclude-api-urls": "FOLLOW_API_URLS=false npm run test:node-local" + "test:node-local-exclude-api-urls": "FOLLOW_API_URLS=false npm run test:node-local", + "catchup": "node scripts/catchup.mjs" }, "devDependencies": { "@ember/optional-features": "^2.0.0", @@ -39,6 +40,7 @@ "broccoli-asset-rev": "^3.0.0", "chai": "^4.3.4", "dictionary-fr": "^2.8.0", + "dotenv": "^16.3.1", "ember-auto-import": "^2.6.1", "ember-cli": "~3.28.6", "ember-cli-app-version": "^5.0.0", @@ -80,8 +82,9 @@ "loader.js": "^4.7.0", "lodash": "^4.17.21", "markdown-link-extractor": "^1.2.2", + "minimist-lite": "^2.2.1", "mocha": "^8.3.2", - "node-fetch": "^2.6.7", + "node-fetch": "^2.7.0", "npm-run-all": "^4.1.5", "prember": "^1.0.3", "prettier": "^2.5.1", @@ -99,6 +102,7 @@ "retext-spell": "^5.3.0", "retext-syntax-urls": "^3.1.2", "sass": "^1.62.1", + "shelljs": "^0.8.5", "unified": "^10.1.2", "walk-sync": "^2.0.2" }, diff --git a/scripts/catchup.mjs b/scripts/catchup.mjs new file mode 100644 index 000000000..fc9a137bb --- /dev/null +++ b/scripts/catchup.mjs @@ -0,0 +1,236 @@ +import 'dotenv/config'; +import fetch from 'node-fetch'; +import fs from 'fs'; +import minimist from 'minimist-lite'; +import shell from 'shelljs'; + +// Declare repository +const repo = 'dazzlingfugu/ember-fr-guides-source'; + +// Read Github token +const token = process.env.GITHUB_TOKEN; + +// Read script arguments +const argv = minimist(process.argv.slice(2)); + +const currentEmberVersion = `${argv.from}`; +if (currentEmberVersion.match(/\d+[.]\d+/g)?.[0] !== currentEmberVersion) { + console.log('Error: please provide the current Ember version under translation to option --from (e.g. --from=5.1)'); + process.exit(2); +} +console.log(`Ember version under translation: ${currentEmberVersion}`); + +const newEmberVersion = `${argv.to}`; +if (newEmberVersion.match(/\d+[.]\d+/g)?.[0] !== newEmberVersion) { + console.log('Error: please provide the new Ember version documented on upstream to option --to (e.g. --to=5.4)'); + process.exit(2); +} +console.log(`New Ember version documented on upstream: ${newEmberVersion}`); + +// Create a catchup branch out of the current branch (should be up to date master) +const catchupBranch = `catchup-${newEmberVersion}`; + +if (shell.exec(`git switch --create ${catchupBranch}`).code !== 0) { + console.log(`shelljs: "git switch --create ${catchupBranch}" command failed`); + process.exit(1); +} +console.log(`shelljs: "git switch --create ${catchupBranch}" executed`); + +// Fetch the latest updates in the official Ember Guides +if (shell.exec('git fetch upstream').code !== 0) { + console.log('shelljs: "git fetch upstream" command failed'); + process.exit(1); +} +console.log('shelljs: "git fetch upstream" executed'); + +// Output the list of markdown files impacted by latest changes on upstream +if (shell.exec('git diff --name-only ref-upstream upstream/master -- guides/release > list.diff').code !== 0) { + console.log('shelljs: "git diff --name-only ref-upstream upstream/master -- guides/release > list.diff" command failed'); + process.exit(1); +} +console.log('shelljs: "git diff --name-only ref-upstream upstream/master -- guides/release > list.diff" executed'); + +// Read list.diff to extract the list of path to markdown files +let data = fs.readFileSync('list.diff', 'utf8'); +let files = data.split(/[\n\r]/).filter(name => name.length); +fs.unlink('list.diff', function(err) { + if (err) throw err; + console.log('list.diff did its job, deleted'); +}); + +// Create a directory to put the children diff +fs.mkdirSync('scripts/patches'); +console.log('scripts/patches folder created to store the patch files'); + +// Compare filename in both branches and output a [index].diff +const createDiff = (filename, index) => { + const diffName = `scripts/patches/${index}.diff` + if (shell.exec(`git diff ref-upstream upstream/master -- ${filename} > ${diffName}`).code !== 0) { + console.log(`shelljs: "git diff ref-upstream upstream/master -- ${filename} > ${diffName}" command failed`); + process.exit(1); + } + console.log(`shelljs: "git diff ref-upstream upstream/master -- ${filename} > ${diffName}" executed`); + return diffName; +} + +// Execute all the read/write/unlink operations on diff files +const writeDiffFiles = async (filesToPost) => { + let writePromises = files.map((filename, index) => { + const diffName = createDiff(filename, index); + return new Promise((resolve, reject) => { + // Rewrite the path to adjust it to our Guidemaker scaffolding + fs.readFile(diffName, 'utf8', function(err, data) { + if (err) reject(err); + const replacement = data.replace(/guides\/release/g, 'guides'); + fs.writeFile(diffName, replacement, 'utf8', function(err) { + if (err) reject(err); + console.log(`path in ${diffName} updated`); + // Try to apply automatically + if (shell.exec(`git apply ${diffName}`).code !== 0) { + shell.echo(`shelljs: "git apply" command failed for ${diffName}`); + filesToPost.push({filename, diffName}) + } else { + // Remove the file if the apply was successfull + fs.unlink(diffName, function(err) { + if (err) throw err; + console.log(`${diffName} handled and deleted`); + }); + } + resolve(); + }); + }); + }); + }); + console.log('Ready to create the patch files'); + await Promise.all(writePromises).then(() => { + console.log('All writing operations are done, patch files are applied or stored in scripts/patches/'); + }); +} + +// Post a GitHub issue +const postIssue = (file) => { + const { filename, diffName } = file; + let diffblock = fs.readFileSync(diffName, 'utf8'); + diffblock = diffblock.replaceAll('```', ''); + let shorterName = filename.substring(14); + + return fetch(`https://api.github.com/repos/${repo}/issues`, { + method: 'POST', + headers: { + 'Accept': 'application/vnd.github+json', + 'Authorization': `token ${token}`, + 'X-GitHub-Api-Version': '2022-11-28' + }, + body: JSON.stringify({ + title: `Translate \`${shorterName}\`, Ember ${newEmberVersion}`, + body: ` +Please assign yourself to the issue or let a comment at the very moment you start the translation. + +File: \`${filename}\` +From Ember: **${currentEmberVersion}** +To Ember: **${newEmberVersion}** + +\`\`\`diff +${diffblock} +\`\`\` + `, + labels: ['Guides FR trad'] + }) + }); +} + +// Try to apply the diff files automatically and keep track of the failed ones +let filesToPost = []; +await writeDiffFiles(filesToPost); +console.log('Files to post on GitHub', filesToPost); + +let issuePostingError = false; + +// Post the diff files content that couldn't be handled automatically to Github +filesToPost.forEach(async (file) => { + try { + console.log(`Attempting to open an issue for ${file.filename}`); + const response = await postIssue(file); + const jsonResponse = await response.json(); + console.log('Server responded with:', jsonResponse); + } catch (error) { + console.log('Issue posting has failed:', error); + issuePostingError = true; + } + await new Promise(resolve => setTimeout(resolve, 1000)); +}); + +if (!issuePostingError) { + // Once the issues are posted, delete patches folder and files + fs.rmSync('scripts/patches', { recursive: true, force: true }); + console.log('scripts/patches folder and files did their job, deleted'); +} +// If one of the post failed, the files are still here so we can easily open the issue manually + +// Add, commit, push the modifications done automatically so far +if (shell.exec('git add guides').code !== 0) { + console.log('shelljs: "git add guides" command failed'); + process.exit(1); +} +console.log('shelljs: "git add guides" executed'); + +if (shell.exec(`git commit -m "feat: automatic catch up from ${currentEmberVersion} to ${newEmberVersion}"`).code !== 0) { + console.log('shelljs: "git commit -m" command failed'); + process.exit(1); +} +console.log('shelljs: "git commit -m" executed'); + +if (shell.exec(`git push origin ${catchupBranch}`).code !== 0) { + console.log(`shelljs: "git push origin ${catchupBranch}" command failed`); + process.exit(1); +} +console.log(`shelljs: "git push origin ${catchupBranch}" executed`); + +// Post the catchup PR +try{ + console.log('Attempting to post the catch up PR'); + const prResponse = await fetch(`https://api.github.com/repos/${repo}/pulls`, { + method: 'POST', + headers: { + 'Accept': 'application/vnd.github+json', + 'Authorization': `token ${token}`, + 'X-GitHub-Api-Version': '2022-11-28' + }, + body: JSON.stringify({ + title: `Catch up latest docs: from ${currentEmberVersion} to ${newEmberVersion}`, + body: 'This is an automatic catch up PR to align our non-translated documentation with the latest official documentation.', + head: catchupBranch, + base: 'master', + labels: ['Guides FR trad'] + }) + }); + const jsonPrResponse = await prResponse.json(); + console.log('Server responded with:', jsonPrResponse); +} catch (error) { + console.log('Catch up PR posting has failed:', error); +} + +// Replace ref-upstream with current upstream then go back to master +if (shell.exec('git switch ref-upstream').code !== 0) { + console.log('shelljs: "git switch ref-upstream" command failed'); + process.exit(1); +} +console.log('shelljs: "git switch ref-upstream" executed'); + +if (shell.exec('git reset --hard upstream/master').code !== 0) { + console.log('shelljs: "git reset --hard upstream/master" command failed'); + process.exit(1); +} +console.log('shelljs: "git reset --hard upstream/master" executed'); + +if (shell.exec('git push origin -f ref-upstream').code !== 0) { + console.log('shelljs: "git push origin -f ref-upstream" command failed'); + process.exit(1); +} +console.log('shelljs: "git push origin -f ref-upstream" executed'); + +if (shell.exec('git switch master').code !== 0) { + console.log('shelljs: "git switch master" command failed'); + process.exit(1); +} +console.log('shelljs: "git switch master" executed'); \ No newline at end of file From 866c4c82a06cf595a4143a036e0d4c923f79f032 Mon Sep 17 00:00:00 2001 From: Marine Dunstetter Date: Fri, 8 Dec 2023 15:20:54 +0100 Subject: [PATCH 2/2] feat: automatic catch up from 5.1 to 5.4 --- guides/code-editors/index.md | 37 +- .../template-lifecycle-dom-and-modifiers.md | 22 +- guides/testing/index.md | 6 +- guides/testing/testing-tools.md | 2 +- guides/typescript/additional-resources/faq.md | 89 +++ .../additional-resources/gotchas.md | 169 ++++ .../typescript/additional-resources/index.md | 18 + .../typescript/additional-resources/legacy.md | 205 +++++ .../application-development/addons.md | 174 +++++ .../application-development/configuration.md | 75 ++ .../converting-an-app.md | 105 +++ .../application-development/index.md | 15 + .../application-development/testing.md | 303 ++++++++ guides/typescript/core-concepts/ember-data.md | 259 +++++++ guides/typescript/core-concepts/index.md | 11 + guides/typescript/core-concepts/invokables.md | 733 ++++++++++++++++++ guides/typescript/core-concepts/routing.md | 132 ++++ guides/typescript/core-concepts/services.md | 115 +++ guides/typescript/getting-started.md | 72 ++ guides/typescript/index.md | 43 + .../current-edition/glimmer-components.md | 34 +- .../current-edition/native-classes.md | 9 +- 22 files changed, 2584 insertions(+), 44 deletions(-) create mode 100644 guides/typescript/additional-resources/faq.md create mode 100644 guides/typescript/additional-resources/gotchas.md create mode 100644 guides/typescript/additional-resources/index.md create mode 100644 guides/typescript/additional-resources/legacy.md create mode 100644 guides/typescript/application-development/addons.md create mode 100644 guides/typescript/application-development/configuration.md create mode 100644 guides/typescript/application-development/converting-an-app.md create mode 100644 guides/typescript/application-development/index.md create mode 100644 guides/typescript/application-development/testing.md create mode 100644 guides/typescript/core-concepts/ember-data.md create mode 100644 guides/typescript/core-concepts/index.md create mode 100644 guides/typescript/core-concepts/invokables.md create mode 100644 guides/typescript/core-concepts/routing.md create mode 100644 guides/typescript/core-concepts/services.md create mode 100644 guides/typescript/getting-started.md create mode 100644 guides/typescript/index.md diff --git a/guides/code-editors/index.md b/guides/code-editors/index.md index 33f8ac56a..d2a038baf 100644 --- a/guides/code-editors/index.md +++ b/guides/code-editors/index.md @@ -7,12 +7,13 @@ many of which are created and maintained by the developer community: Visual Studio Code is a code editor optimized for building and debugging modern web applications. Visual Studio Code is one of the most popular text editors among Ember developers. -### Syntax Highlighting +### Extension Pack + +Install the extension pack to get everything you need to work on Ember.js projects. -Only one of these is needed. +[Ember.js Extension Pack](https://marketplace.visualstudio.com/items?itemName=EmberTooling.emberjs) - It will install the following addons -[VSCode Glimmer](https://marketplace.visualstudio.com/items?itemName=chiragpat.vscode-glimmer) - -Provides embedded template highlighting support. +### Syntax Highlighting [Glimmer Templates Syntax](https://marketplace.visualstudio.com/items?itemName=lifeart.vscode-glimmer-syntax) - Syntax formatting for glimmer templates. @@ -22,10 +23,9 @@ Syntax formatting for glimmer templates. [Stable Ember Language Server](https://marketplace.visualstudio.com/items?itemName=lifeart.vscode-ember-unstable) - Stable Ember Language Server is a stable, full-featured language server. Its name comes from its history as a fork of Ember Language Server and the efforts to keep up with changes in Ember. -### Snippets / Workflow +### Workflow -[Ember JS (ES6) and Handlebars code snippets](https://marketplace.visualstudio.com/items?itemName=phanitejakomaravolu.EmberES6Snippets) - -Enables Ember.js and Handlebars snippets to let you to type less and code more. +[ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) - Integrates ESLint into VS Code. [EditorConfig for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) - Attempts to override user/workspace settings with settings found in `.editorconfig` files. @@ -35,9 +35,21 @@ and maintain consistent coding styles between different editors and IDEs. [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) - Prettier is an opinionated code formatting tool. It enforces a consistent style by parsing your code and re-printing it with its own rules that take the maximum line length into account, wrapping code when necessary. Prettier supports Handlebars, Ember and Glimmer out of the box. -### Glimmer templates +### Typed Glimmer Templates + +
+
+
+
Zoey says...
+
+ This is not installed as part of the extension pack but should be considered for Ember projects built with TypeScript. Learn more about Glint here. +
+
+ +
+
-[Glint](https://marketplace.visualstudio.com/items?itemName=typed-ember.glint-vscode) is a set of tools to aid in developing code that uses the Glimmer VM for rendering, such as Ember.js v3.24+ and GlimmerX projects. +[Glint](https://marketplace.visualstudio.com/items?itemName=typed-ember.glint-vscode) is a set of tools to aid in developing code that uses the Glimmer VM for rendering, such as Ember.js v3.24+ and GlimmerX projects. ## Vim and Neovim @@ -63,10 +75,10 @@ or [vim-ember-hbs](https://github.com/joukevandermaas/vim-ember-hbs) - Add Ember template syntax highlighting and indentation to Vim. To get embedded highlighting will involve these additional plugins: + - [vim-javascript](https://github.com/pangloss/vim-javascript) - [vim-js-pretty-template](https://github.com/Quramy/vim-js-pretty-template) - ### Language Server Only one of these solutions should be used at a time. @@ -78,21 +90,18 @@ Example mason+LSP config [can be found here](https://github.com/NullVoxPopuli/do or [Conquer for Completion (COC) for Neovim](https://github.com/neoclide/coc.nvim) - -An Intellisense engine which takes control over all linting, hinting, and language-server integration. +An IntelliSense engine which takes control over all linting, hinting, and language-server integration. With the ember plugin [coc-ember](https://github.com/NullVoxPopuli/coc-ember) - Ember.js language server extension including useful configuration instructions. ### Snippets / Workflow - [ember.vim](https://github.com/dsawardekar/ember.vim) - Shortcuts to navigate related files with Ember.js projects. - [Ember Tools](https://github.com/AndrewRadev/ember_tools.vim) - Various tools for working with Ember.js projects. - ## Atom Atom is hackable text editor for the 21st Century. diff --git a/guides/components/template-lifecycle-dom-and-modifiers.md b/guides/components/template-lifecycle-dom-and-modifiers.md index b8fb711cf..13fa0e8c5 100644 --- a/guides/components/template-lifecycle-dom-and-modifiers.md +++ b/guides/components/template-lifecycle-dom-and-modifiers.md @@ -293,10 +293,17 @@ The modifier that we're going to build will allow us to say: Pretty nice, right? -To accomplish that, we'll create a modifier in `app/modifiers/autofocus.js`. First, install [`ember-modifier`](https://github.com/ember-modifier/ember-modifier) and then generate an `autofocus` modifier for your app: +New Ember apps ship with a dependency on +[ember-modifier](https://github.com/ember-modifier/ember-modifier), which +provides a friendly API for writing your own element modifiers. This library is +in turn based on a low level API named _modifier managers_. Managers are a +framework-development level feature, and not something most developers need to +interact with. You'll see in the following examples that the modifier API is +imported from the `ember-modifier` package. + +First generate the `autofocus` modifier for your application: ```bash -ember install ember-modifier ember generate modifier autofocus ``` @@ -308,9 +315,10 @@ import { modifier } from "ember-modifier"; export default modifier(element => element.focus()); ``` -And that's it! +And that's it! Now we can use our custom `{{autofocus}}` modifier throughout our application. -Now we can use our custom `{{autofocus}}` modifier throughout our application. +Read more about the `ember-modifier` APIs at [ember-modifiers: +Usage](https://github.com/ember-modifier/ember-modifier#usage). ## Communicating Between Elements in a Component @@ -390,7 +398,6 @@ export default class AudioPlayerComponent extends Component { That's it for the component: we're translating the user's interactions into _state_. Now we need to build a modifier to translate the state into the appropriate DOM method calls! ```bash -ember install ember-modifier ember generate modifier play-when ``` @@ -448,12 +455,11 @@ document.addEventListener("click", event => { The most important difference between this example and the cases we've seen so far is that we need to remove the `click` event handler from the document when this element is destroyed. -To accomplish this, we can use [`ember-modifier`](https://github.com/ember-modifier/ember-modifier) to create a `on-click-outside` modifier that sets up the event listener after the element is first inserted and removes the event listener when the element is removed. +To accomplish this, we can use [`ember-modifier`](https://github.com/ember-modifier/ember-modifier) (which is already installed in newly generated Ember apps) to create a `on-click-outside` modifier that sets up the event listener after the element is first inserted and removes the event listener when the element is removed. -Run the following commands to install the addon and generate a new modifier: +Generate the new modifier: ```bash -ember install ember-modifier ember generate modifier on-click-outside ``` diff --git a/guides/testing/index.md b/guides/testing/index.md index af9460b05..46eb499a6 100644 --- a/guides/testing/index.md +++ b/guides/testing/index.md @@ -34,7 +34,7 @@ ember t -s When you are working on a single component or page, you will want only a small subset of tests to run after every file change. To specify which tests to run, you can add `--module` or `--filter` option to your command. -The `--module` option allows you to select a **module**—a group of tests that you specified in `module()` in QUnit, or `describe()` in Mocha. +The `--module` option allows you to select a **module**—a group of tests that you specified in `module()` in QUnit. ```bash # Button component example @@ -44,7 +44,7 @@ ember test --server --module="Integration | Component | simple-button" ember t -s -m="Unit | Service | location" ``` -The `--filter` option is more versatile. You can provide a phrase to match against the modules and test descriptions. A test description is what appears in `test()` in QUnit, or `it()` in Mocha. +The `--filter` option is more versatile. You can provide a phrase to match against the modules and test descriptions. A test description is what appears in `test()` in QUnit. ```bash # Button component example @@ -57,7 +57,7 @@ ember t -s -f="Dashboard" ember t -s -f="Integration" ``` -In QUnit, you can exclude tests by adding an exclamation point to the beginning of the filter, e.g. `ember test --filter="!Acceptance"`. In Mocha, `ember test --filter="Acceptance" --invert`. +In QUnit, you can exclude tests by adding an exclamation point to the beginning of the filter, e.g. `ember test --filter="!Acceptance"`. To learn more about options for testing, you can visit [Ember CLI Documentation](https://ember-cli.com/testing) or type `ember help test` in the command line. diff --git a/guides/testing/testing-tools.md b/guides/testing/testing-tools.md index 222e82d45..71e50bfa3 100644 --- a/guides/testing/testing-tools.md +++ b/guides/testing/testing-tools.md @@ -164,6 +164,6 @@ While we don't recommend this practice in general, you might also use Percy in l ## Summary -Ember provides easy paths to integrate QUnit and Mocha, also it supports a variety of addons and debugging tools to improve your developer experience in testing. +Ember provides easy paths to integrate QUnit and it also supports a variety of addons and debugging tools to improve your developer experience in testing. In the next section, we will study 3 types of tests that Ember supports—unit, rendering, and application tests. We will look at each type and when you might use one over another. diff --git a/guides/typescript/additional-resources/faq.md b/guides/typescript/additional-resources/faq.md new file mode 100644 index 000000000..561555734 --- /dev/null +++ b/guides/typescript/additional-resources/faq.md @@ -0,0 +1,89 @@ +## What about missing types? + +### Gradually typing your app + +See ["Gradual Typing Hacks"][gradual-typing-hacks] for strategies for incrementally adding types to your app. + +### Install types for libraries + +You'll want to use library type definitions as much as possible. Many packages ship their own type definitions, and many others have community-maintained definitions from [DefinitelyTyped][], available in the `@types` name space. The first thing you should do is to look for types from other libraries: it will mean using fewer ["Gradual Typing Hacks"][gradual-typing-hacks] and getting a lot more help both from your editor and from the compiler. + +### The `types` directory + +During installation, we create a `types` directory in the root of your application and add a [`"paths"`][tsconfig-paths] mapping to your `tsconfig.json` that includes that directory in any type lookups TypeScript tries to do. This is convenient for a few things: + +- global types for your project (see the next section) +- writing types for libraries that do not have any types + +These are all fallbacks, of course, you should use the types supplied directly with a package when possible. + +#### Global types for your project + +At the root of your application or addon, we include a `types/` directory with an `index.d.ts` file in it. Anything which is part of your project but which must be declared globally can go in this file. For example, if you have data attached to the `Window` object when the page is loaded (for bootstrapping or whatever other reason), this is a good place to declare it. + +We automatically configure `index.d.ts` to be ready for [Glint][], which will make type checking work with Ember's templates. The default configuration only supports Ember's classic pairing of separate `.ts` and `.hbs` files, but Glint also supports the `