├── .editorconfig ├── .eslintrc.base.js ├── .eslintrc.json ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.md └── workflows │ ├── CI.yaml │ ├── browsers-full.yaml │ ├── browsers-quick.yaml │ ├── coverage.yaml │ ├── github-pages.yaml │ ├── reproducible.yaml │ ├── spider-check.yaml │ └── typesense.yaml ├── .gitignore ├── .mailmap ├── AUTHORS.txt ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Gruntfile.js ├── History.md ├── LICENSE.txt ├── README.md ├── RELEASE.md ├── SECURITY.md ├── bin └── qunit.js ├── build ├── browserstack-debug.json ├── browserstack-full.json ├── browserstack-quick.json ├── coverage-bridge.js ├── dev.js ├── dist-replace.js ├── hydra-config.json ├── npm-search.js ├── prep-release.js ├── q4000-template.js ├── reproducible-builds.js ├── review-package.js ├── site-set-version.js ├── site-update-plugins.js ├── tasks │ └── test-on-node.js └── utils.js ├── demos ├── bundlers.mjs ├── bundlers │ ├── Gruntfile.js │ ├── README.md │ ├── build.mjs │ ├── favicon.ico │ ├── package.json │ └── test │ │ ├── .eslintrc.json │ │ ├── import-default.js │ │ ├── import-indirect.js │ │ ├── import-named.js │ │ ├── package.json │ │ ├── require-default.cjs │ │ ├── require-indirect.cjs │ │ ├── require-sub.cjs │ │ └── src.js ├── grunt-contrib-qunit.js ├── grunt-contrib-qunit │ ├── Gruntfile.js │ ├── README.md │ ├── fail-assert.html │ ├── fail-no-tests.html │ ├── fail-uncaught.html │ ├── package.json │ ├── pass-basic.html │ └── qunit ├── karma-qunit.js ├── karma-qunit │ ├── README.md │ ├── fail-assert.js │ ├── fail-global-error.js │ ├── karma.conf.js │ ├── package.json │ ├── pass-basic.js │ └── pass-config.js ├── nyc.js ├── nyc │ ├── .gitignore │ ├── README.md │ ├── index.js │ ├── package.json │ ├── src │ │ ├── add.js │ │ └── subtract.js │ └── test │ │ └── add.js ├── q4000-qunit.html ├── q4000-qunit.js ├── qunit-config-maxDepth.html ├── qunit-fail.html ├── qunit-onerror-early.html ├── testem.js └── testem │ ├── README.md │ ├── add.js │ ├── add.test.js │ ├── package.json │ ├── qunit │ ├── test.html │ └── testem.json ├── docs ├── 404.md ├── CNAME ├── Gemfile ├── README.md ├── _config.yml ├── _data │ ├── authors.yaml │ ├── plugins.json │ ├── projects.yml │ ├── sidebar_api.yml │ ├── sidebar_blog.yml │ └── sitenav.yml ├── _posts │ ├── 2011-10-06-qunit-1-0-0.md │ ├── 2011-10-11-qunit-1-1-0.md │ ├── 2011-11-24-qunit-1-2-0.md │ ├── 2012-02-26-qunit-1-3-0.md │ ├── 2012-03-10-qunit-1-4-0.md │ ├── 2012-04-04-qunit-1-5-0.md │ ├── 2012-05-04-qunit-1-6-0.md │ ├── 2012-06-07-qunit-1-7-0.md │ ├── 2012-06-14-qunit-1-8-0.md │ ├── 2012-07-11-qunit-1-9-0.md │ ├── 2012-08-30-qunit-1-10-0.md │ ├── 2013-01-20-qunit-1-11-0.md │ ├── 2013-06-21-qunit-1-12-0.md │ ├── 2014-01-04-qunit-1-13-0.md │ ├── 2014-01-31-qunit-1-14-0.md │ ├── 2014-08-08-qunit-1-15-0.md │ ├── 2014-12-03-qunit-1-16-0.md │ ├── 2015-01-19-qunit-1-17-0.md │ ├── 2015-01-20-qunit-1-17-1.md │ ├── 2015-04-03-qunit-1-18-0.md │ ├── 2015-09-01-qunit-1-19-0.md │ ├── 2015-10-27-qunit-1-20-0.md │ ├── 2016-02-01-qunit-1-21-0.md │ ├── 2016-02-23-qunit-1-22-0.md │ ├── 2016-03-25-qunit-1-23-0.md │ ├── 2016-04-12-qunit-1-23-1.md │ ├── 2016-04-21-introduce-multi-select-module-picker.md │ ├── 2016-06-16-qunit-2-0-0.md │ ├── 2016-07-23-qunit-2-0-1.md │ ├── 2016-12-05-qunit-2-1-0.md │ ├── 2017-01-05-qunit-2-1-1.md │ ├── 2017-03-11-qunit-2-2-0.md │ ├── 2017-03-19-qunit-2-2-1.md │ ├── 2017-03-29-qunit-2-3-0.md │ ├── 2017-04-10-qunit-2-3-1.md │ ├── 2017-04-17-qunit-2-3-2.md │ ├── 2017-06-02-qunit-2-3-3.md │ ├── 2017-07-08-qunit-2-4-0.md │ ├── 2017-10-21-qunit-2-4-1.md │ ├── 2018-01-09-qunit-2-5-0.md │ ├── 2018-02-27-qunit-2-5-1.md │ ├── 2018-03-26-qunit-2-6-0.md │ ├── 2018-05-15-qunit-2-6-1.md │ ├── 2018-08-19-qunit-2-6-2.md │ ├── 2018-10-10-qunit-2-7-0.md │ ├── 2018-10-17-qunit-2-7-1.md │ ├── 2018-11-02-qunit-2-8-0.md │ ├── 2019-01-06-qunit-2-9-0.md │ ├── 2019-01-07-qunit-2-9-1.md │ ├── 2019-02-21-qunit-2-9-2.md │ ├── 2019-10-08-qunit-2-9-3.md │ ├── 2020-05-02-qunit-2-10-0.md │ ├── 2020-07-04-qunit-2-10-1.md │ ├── 2020-08-16-qunit-2-11-0.md │ ├── 2020-08-25-qunit-2-11-1.md │ ├── 2020-09-09-qunit-2-11-2.md │ ├── 2020-10-05-qunit-2-11-3.md │ ├── 2020-11-08-qunit-2-12-0.md │ ├── 2020-11-29-qunit-2-13-0.md │ ├── 2021-01-12-qunit-2-14-0.md │ ├── 2021-03-14-qunit-2-14-1.md │ ├── 2021-04-12-qunit-2-15-0.md │ ├── 2021-06-06-qunit-2-16-0.md │ ├── 2021-09-05-qunit-2-17-0.md │ ├── 2021-09-09-qunit-2-17-1.md │ ├── 2021-09-19-qunit-2-17-2.md │ ├── 2022-02-15-qunit-2-18-0.md │ ├── 2022-03-29-qunit-2-18-1.md │ ├── 2022-04-16-redesign-module-selector.md │ ├── 2022-04-17-qunit-2-18-2.md │ ├── 2022-04-28-qunit-2-19-0.md │ ├── 2022-05-01-qunit-2-19-1.md │ ├── 2022-10-17-qunit-2-19-2.md │ ├── 2022-10-22-qunit-2-19-3.md │ ├── 2023-01-23-qunit-2-19-4.md │ ├── 2023-09-23-qunit-2-20-0.md │ ├── 2024-02-15-qunit-2-20-1.md │ ├── 2024-05-29-qunit-2-21-0.md │ ├── 2024-07-20-qunit-2-21-1.md │ ├── 2024-08-18-qunit-2-22-0.md │ ├── 2024-12-03-qunit-2-23-0.md │ ├── 2024-12-06-qunit-2-23-1.md │ ├── 2025-01-19-stacktrace-cleaner.md │ ├── 2025-01-20-qunit-2-24-0.md │ ├── 2025-01-25-qunit-2-24-1.md │ └── 2025-04-20-test-lifecycle.md ├── _sass │ ├── amethyst-variables.scss │ └── custom.scss ├── about.md ├── api │ ├── QUnit │ │ ├── hooks.md │ │ ├── index.md │ │ ├── load.md │ │ ├── module.md │ │ ├── start.md │ │ ├── test.each.md │ │ ├── test.if.md │ │ ├── test.md │ │ ├── test.only.md │ │ ├── test.skip.md │ │ └── test.todo.md │ ├── assert │ │ ├── async.md │ │ ├── closeTo.md │ │ ├── deepEqual.md │ │ ├── equal.md │ │ ├── expect.md │ │ ├── false.md │ │ ├── index.md │ │ ├── notDeepEqual.md │ │ ├── notEqual.md │ │ ├── notOk.md │ │ ├── notPropContains.md │ │ ├── notPropEqual.md │ │ ├── notStrictEqual.md │ │ ├── ok.md │ │ ├── propContains.md │ │ ├── propEqual.md │ │ ├── push.md │ │ ├── pushResult.md │ │ ├── rejects.md │ │ ├── step.md │ │ ├── strictEqual.md │ │ ├── throws.md │ │ ├── timeout.md │ │ ├── true.md │ │ └── verifySteps.md │ ├── async.md │ ├── callbacks │ │ ├── QUnit.begin.md │ │ ├── QUnit.done.md │ │ ├── QUnit.log.md │ │ ├── QUnit.moduleDone.md │ │ ├── QUnit.moduleStart.md │ │ ├── QUnit.on.md │ │ ├── QUnit.testDone.md │ │ ├── QUnit.testStart.md │ │ └── index.md │ ├── config │ │ ├── altertitle.md │ │ ├── autostart.md │ │ ├── collapse.md │ │ ├── countStepsAsOne.md │ │ ├── current.md │ │ ├── failOnZeroTests.md │ │ ├── filter.md │ │ ├── fixture.md │ │ ├── hidepassed.md │ │ ├── index.md │ │ ├── maxDepth.md │ │ ├── module.md │ │ ├── moduleId.md │ │ ├── modules.md │ │ ├── noglobals.md │ │ ├── notrycatch.md │ │ ├── reorder.md │ │ ├── reporters.md │ │ ├── requireExpects.md │ │ ├── scrolltop.md │ │ ├── seed.md │ │ ├── storage.md │ │ ├── testId.md │ │ ├── testTimeout.md │ │ └── urlConfig.md │ ├── deprecated.md │ ├── extension │ │ ├── QUnit.assert.md │ │ ├── QUnit.dump.parse.md │ │ ├── QUnit.dump.setParser.md │ │ ├── QUnit.extend.md │ │ ├── QUnit.onUncaughtException.md │ │ ├── QUnit.stack.md │ │ ├── QUnit.urlParams.md │ │ └── index.md │ ├── index.md │ ├── removed.md │ └── reporters │ │ ├── console.md │ │ ├── html.md │ │ ├── index.md │ │ ├── perf.md │ │ └── tap.md ├── badge.md ├── blog.md ├── blog │ ├── archive.md │ └── tag │ │ ├── feature.md │ │ └── release.md ├── brand.md ├── browser.md ├── cli.md ├── favicon.ico ├── favicon.svg ├── img │ ├── 2011-logo-qunit.png │ ├── 2012-logo-qunit.png │ ├── 2012-logo-qunit@2x.png │ ├── 2012-website-qunit.png │ ├── 2012b-logo-qunit.png │ ├── 2013-logo-qunit_color_study.png │ ├── 2013-website-qunit.png │ ├── 2020-website-qunit.png │ ├── QUnit-Logo-Large.png │ ├── logo-qunit@2x.png │ ├── logo-text.svg │ ├── logo-with-colored-dark-text.svg │ ├── logo-with-colored-text.svg │ ├── logo.png │ └── logo.svg ├── index.md ├── intro.md ├── lifecycle.md ├── plugins.md ├── projects.md ├── resources │ ├── 2025-stacktrace-assert-html.png │ ├── 2025-stacktrace-assert-tap-after.png │ ├── 2025-stacktrace-assert-tap-before.png │ ├── 2025-stacktrace-error-after.png │ ├── 2025-stacktrace-error-before.png │ ├── calc.js │ ├── calc.test.js │ ├── example-add.html │ ├── example-fail.html │ ├── example-index.html │ ├── game.js │ ├── game.test.js │ ├── perf-chrome.png │ ├── perf-firefox.png │ ├── q4000.html │ └── qunit-lifecycle-hooks-order.svg ├── testedwith.svg └── upgrade-guide-2.x.md ├── docsearch.config.json ├── lib └── promise-polyfill.js ├── package.json ├── rollup.config.js ├── src ├── cli │ ├── find-reporter.js │ ├── require-from-cwd.js │ ├── require-qunit.js │ ├── run.js │ └── utils.js └── core │ ├── assert.js │ ├── browser │ ├── browser-runner.js │ ├── fixture.js │ └── urlparams.js │ ├── callbacks.js │ ├── config.js │ ├── diff.js │ ├── dump.js │ ├── equiv.js │ ├── events.js │ ├── globals.js │ ├── hooks.js │ ├── logger.js │ ├── module.js │ ├── on-uncaught-exception.js │ ├── processing-queue.js │ ├── promise.js │ ├── qunit-commonjs.js │ ├── qunit-wrapper-bundler-require.js │ ├── qunit-wrapper-nodejs-module.js │ ├── qunit.css │ ├── qunit.js │ ├── reporters.js │ ├── reporters │ ├── ConsoleReporter.js │ ├── HtmlReporter.js │ ├── PerfReporter.js │ └── TapReporter.js │ ├── reports │ ├── suite.js │ └── test.js │ ├── stacktrace.js │ ├── start.js │ ├── test.js │ ├── urlparams.js │ ├── utilities.js │ └── version.js └── test ├── benchmark ├── README.md ├── micro-bench.js ├── micro-fixture.js ├── micro.html ├── micro.js ├── package.json └── q4000.json ├── browser-runner ├── amd.html ├── amd.js ├── autostart.html ├── autostart.js ├── config-fixture-null.html ├── config-fixture-null.js ├── config-fixture-string.html ├── config-fixture-string.js ├── headless.html ├── window-onerror-preexisting-handler.html ├── window-onerror-preexisting-handler.js ├── window-onerror.html └── window-onerror.js ├── cli ├── ConsoleReporter.js ├── PerfReporter.js ├── TapReporter-to-TapParser.js ├── cli-main.js ├── cli-watch.js ├── custom-reporter.js ├── fixtures │ ├── .gitignore │ ├── _load-default.tap.txt │ ├── _load-dir-file-glob.tap.txt │ ├── _load-dir.tap.txt │ ├── _load-filenotfound.tap.txt │ ├── _load-glob.tap.txt │ ├── _load-multiple-files.tap.txt │ ├── _load-single-file.tap.txt │ ├── _sourcemap.tap.txt │ ├── assert-expect-failure-step.js │ ├── assert-expect-failure-step.tap.txt │ ├── assert-expect-failure.js │ ├── assert-expect-failure.tap.txt │ ├── assert-expect-no-assertions.js │ ├── assert-expect-no-assertions.tap.txt │ ├── assert-failure.js │ ├── assert-failure.tap.txt │ ├── assert-throws-failure.js │ ├── assert-throws-failure.tap.txt │ ├── async-module-error-promise.js │ ├── async-module-error-promise.tap.txt │ ├── async-module-error-thenable.js │ ├── async-module-error-thenable.tap.txt │ ├── async-module-error.js │ ├── async-module-error.tap.txt │ ├── async-test-throw.js │ ├── async-test-throw.tap.txt │ ├── basic-fail.js │ ├── basic-one.js │ ├── basic-two.js │ ├── callbacks-promises.js │ ├── callbacks-promises.tap.txt │ ├── callbacks-rejected.js │ ├── callbacks-rejected.tap.txt │ ├── callbacks.js │ ├── callbacks.tap.txt │ ├── config-filter-regex-exclude.js │ ├── config-filter-regex-exclude.tap.txt │ ├── config-filter-regex.js │ ├── config-filter-regex.tap.txt │ ├── config-filter-string.js │ ├── config-filter-string.tap.txt │ ├── config-module.js │ ├── config-module.tap.txt │ ├── config-moduleId.js │ ├── config-moduleId.tap.txt │ ├── config-noglobals-add.js │ ├── config-noglobals-add.tap.txt │ ├── config-noglobals-ignored.js │ ├── config-noglobals-ignored.tap.txt │ ├── config-noglobals-remove.js │ ├── config-noglobals-remove.tap.txt │ ├── config-notrycatch-hook-rejection.js │ ├── config-notrycatch-hook-rejection.tap.txt │ ├── config-notrycatch-test-rejection.js │ ├── config-notrycatch-test-rejection.tap.txt │ ├── config-requireExpects.js │ ├── config-requireExpects.tap.txt │ ├── config-testId.js │ ├── config-testId.tap.txt │ ├── config-testTimeout-invalid.js │ ├── config-testTimeout-invalid.tap.txt │ ├── config-testTimeout.js │ ├── config-testTimeout.tap.txt │ ├── done-after-timeout.js │ ├── done-after-timeout.tap.txt │ ├── drooling-done.js │ ├── drooling-done.tap.txt │ ├── drooling-extra-done-outside.js │ ├── drooling-extra-done-outside.tap.txt │ ├── drooling-extra-done.js │ ├── drooling-extra-done.tap.txt │ ├── each-array-labels.js │ ├── each-array-labels.tap.txt │ ├── event-runEnd-memory.js │ ├── event-runEnd-memory.tap.txt │ ├── events.js │ ├── events.tap.txt │ ├── filter-modulename-insensitive.tap.txt │ ├── filter-modulename.tap.txt │ ├── glob │ │ ├── a-test.js │ │ ├── not-a.js │ │ └── sub │ │ │ └── nested-test.js │ ├── hanging-test.js │ ├── hanging-test.tap.txt │ ├── hooks-global-context.js │ ├── hooks-global-context.tap.txt │ ├── hooks-global-order.js │ ├── hooks-global-order.tap.txt │ ├── hooks-global-throw.js │ ├── hooks-global-throw.tap.txt │ ├── inception.js │ ├── inception.tap.txt │ ├── memory-leak-module-closure-filtered.tap.txt │ ├── memory-leak-module-closure-unfiltered.tap.txt │ ├── memory-leak-module-closure.js │ ├── memory-leak-test-object.js │ ├── memory-leak-test-object.tap.txt │ ├── module-nested.js │ ├── module-nested.tap.txt │ ├── no-tests-failOnZeroTests.js │ ├── no-tests-failOnZeroTests.tap.txt │ ├── no-tests.js │ ├── no-tests.tap.txt │ ├── node_modules │ │ └── require-dep │ │ │ ├── index.js │ │ │ ├── module.js │ │ │ └── package.json │ ├── npm-reporter │ │ ├── index.js │ │ └── package.json │ ├── only-module-flat.js │ ├── only-module-flat.tap.txt │ ├── only-module-then-test.js │ ├── only-module-then-test.tap.txt │ ├── only-module.js │ ├── only-module.tap.txt │ ├── only-test-only-module-mix.js │ ├── only-test-only-module-mix.tap.txt │ ├── only-test.js │ ├── only-test.tap.txt │ ├── pending-async-after-timeout.js │ ├── pending-async-after-timeout.tap.txt │ ├── perf-mark.js │ ├── perf-mark.tap.txt │ ├── preconfig-flat.js │ ├── preconfig-flat.tap.txt │ ├── require-module-and-script.tap.txt │ ├── seed.tap.txt │ ├── sourcemap │ │ ├── source.js │ │ ├── source.min.js │ │ └── source.min.js.map │ ├── syntax-error.js │ ├── syntax-error.tap.txt │ ├── test-if.js │ ├── test-if.tap.txt │ ├── test │ │ ├── extension.cjs │ │ ├── extension.mjs │ │ ├── extension.ts │ │ ├── extension.txt │ │ ├── first.js │ │ └── nested │ │ │ └── second.js │ ├── timeout.js │ ├── timeout.tap.txt │ ├── too-many-done-calls.js │ ├── too-many-done-calls.tap.txt │ ├── uncaught-error-after-assert-async.js │ ├── uncaught-error-after-assert-async.tap.txt │ ├── uncaught-error-callback-moduleDone.js │ ├── uncaught-error-callback-moduleDone.tap.txt │ ├── uncaught-error-callback-testStart.js │ ├── uncaught-error-callback-testStart.tap.txt │ ├── uncaught-error-callbacks-begin.js │ ├── uncaught-error-callbacks-begin.tap.txt │ ├── uncaught-error-callbacks-done.js │ ├── uncaught-error-callbacks-done.tap.txt │ ├── uncaught-error-in-hook.js │ ├── uncaught-error-in-hook.tap.txt │ ├── unhandled-rejection.js │ ├── unhandled-rejection.tap.txt │ ├── zero-assertions.js │ └── zero-assertions.tap.txt ├── helpers │ ├── execute.js │ └── fixtures.js ├── require-qunit-test.js ├── structure.js └── utils.js ├── config-reporters.html ├── dynamic-import.html ├── dynamic-import ├── bar.js ├── foo.js ├── index.js └── sum.mjs ├── events-filters.html ├── events-filters.js ├── events-in-test.html ├── events-in-test.js ├── index-xhtml.xhtml ├── index.html ├── logs.html ├── logs.js ├── main ├── HtmlReporter.js ├── TapReporter.js ├── assert-es6.js ├── assert-step.js ├── assert-timeout.js ├── assert.js ├── async.js ├── browser-runner.js ├── callbacks.js ├── deepEqual.js ├── diff.js ├── dump.js ├── each.js ├── events.js ├── legacy.js ├── modules-es2018.js ├── modules-esm.mjs ├── modules.js ├── onUncaughtException.js ├── promise.js ├── setTimeout.js ├── stacktrace.js ├── test.js └── utilities.js ├── module-skip.html ├── module-skip.js ├── module-todo.html ├── module-todo.js ├── mozjs.js ├── mozjs.mjs ├── node ├── storage-1.js ├── storage-2.js └── storage.js ├── only-each.html ├── only-each.js ├── overload.html ├── perf-clear-marks.html ├── perf-clear-marks.js ├── perf-mark.html ├── perf-mark.js ├── preconfig-flat-reporters.html ├── preconfig-flat-testId.html ├── preconfig-flat-testId.js ├── preconfig-flat.html ├── preconfig-flat.js ├── preconfig-object.html ├── preconfig-object.js ├── reorder.html ├── reorder.js ├── reorderError1.html ├── reorderError1.js ├── reorderError2.html ├── reorderError2.js ├── reporter-urlparams.html ├── reporter-urlparams.js ├── sandboxed-iframe--contents.html ├── sandboxed-iframe.html ├── sandboxed-iframe.js ├── seed.html ├── seed.js ├── startError.html ├── startError.js ├── urlparams-filter.html ├── urlparams-filter.js ├── urlparams-module.html ├── urlparams-module.js ├── urlparams-moduleId.html ├── urlparams-moduleId.js ├── urlparams-testId.html ├── urlparams-testId.js ├── webWorker-worker.js ├── webWorker.html └── webWorker.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [demos/grunt-contrib-qunit.js] 14 | trim_trailing_whitespace = false 15 | [demos/nyc.js] 16 | trim_trailing_whitespace = false 17 | [test/cli/TapReporter.js] 18 | trim_trailing_whitespace = false 19 | 20 | [*.css] 21 | indent_style = tab 22 | -------------------------------------------------------------------------------- /.eslintrc.base.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | // This JS file exists to reset 'env' and 'globals', 4 | // which ESLint doesn't have a built-in way to do otherwise. 5 | // Because of this, we have to bypass semistandard. 6 | const standard = require('eslint-config-standard'); 7 | 8 | const config = Object.assign(standard, { 9 | env: {}, 10 | globals: {}, 11 | rules: Object.assign(standard.rules, { 12 | // semistandard 13 | semi: ['error', 'always'], 14 | 'no-extra-semi': 'error', 15 | // disablements 16 | 'n/no-callback-literal': 'off', 17 | 'no-lone-blocks': 'off', 18 | 'object-shorthand': 'off', 19 | 'prefer-const': 'off', 20 | 'prefer-promise-reject-errors': 'off', 21 | // extra 22 | 'operator-linebreak': ['error', 'before', { overrides: { '=': 'after', '+=': 'after' } }], 23 | eqeqeq: ['error'], 24 | 'no-unused-vars': ['error', { args: 'all', argsIgnorePattern: '^_' }] 25 | }) 26 | }); 27 | 28 | module.exports = config; 29 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # JS and HTML files must always use LF for tools to work 5 | *.js eol=lf 6 | *.tap.txt eol=lf 7 | *.json eol=lf 8 | *.html eol=lf 9 | -------------------------------------------------------------------------------- /.github/workflows/reproducible.yaml: -------------------------------------------------------------------------------- 1 | name: Reproducible builds 2 | on: 3 | # Once a week on Monday at 00:30 UTC 4 | schedule: 5 | - cron: '30 0 * * 1' 6 | # Or manually 7 | workflow_dispatch: 8 | 9 | jobs: 10 | run: 11 | name: Verify releases 12 | if: ${{ github.repository == 'qunitjs/qunit' }} # skip noisy cron on forks 13 | runs-on: ubuntu-22.04 14 | steps: 15 | - uses: actions/checkout@v4 16 | 17 | - name: Use Node.js 18 18 | uses: actions/setup-node@v4 19 | with: 20 | node-version: 18.x 21 | 22 | - run: node build/reproducible-builds.js 23 | -------------------------------------------------------------------------------- /.github/workflows/spider-check.yaml: -------------------------------------------------------------------------------- 1 | name: spider-check 2 | on: 3 | # Once a week on Friday at 00:00 4 | schedule: 5 | - cron: '0 0 * * 5' 6 | # Or manually 7 | workflow_dispatch: 8 | 9 | jobs: 10 | spider-check: 11 | if: ${{ github.repository_owner == 'qunitjs' }} # skip on forks 12 | runs-on: ubuntu-latest 13 | env: 14 | # Site address to crawl 15 | # 16 | # Example: 17 | # - https://example.org 18 | # - https://example.github.io/ 19 | # - https://example.github.io/my-project/ 20 | MY_SITE: https://qunitjs.com 21 | steps: 22 | - uses: actions/checkout@v4 23 | 24 | - name: Run hydra-link-checker 25 | run: | 26 | curl -O https://raw.githubusercontent.com/jquery/hydra-link-checker/v2.0.0/hydra.py 27 | python3 hydra.py "$MY_SITE" --config build/hydra-config.json 28 | -------------------------------------------------------------------------------- /.github/workflows/typesense.yaml: -------------------------------------------------------------------------------- 1 | name: typesense 2 | on: 3 | # Once a day at 11:30 UTC 4 | schedule: 5 | - cron: '30 11 * * *' 6 | # Or after a deployment 7 | push: 8 | branches: 9 | - main 10 | # Or manually 11 | workflow_dispatch: 12 | 13 | jobs: 14 | typesense: 15 | name: Update Typesense 16 | if: ${{ github.repository_owner == 'qunitjs' }} # skip on forks 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v4 20 | - name: Docsearch Scraper 21 | shell: bash 22 | run: | 23 | docker run \ 24 | -e TYPESENSE_API_KEY=${{ secrets.TYPESENSE_ADMIN_KEY }} \ 25 | -e TYPESENSE_HOST="${{ secrets.TYPESENSE_HOST }}" \ 26 | -e TYPESENSE_PORT="443" \ 27 | -e TYPESENSE_PROTOCOL="https" \ 28 | -e CONFIG="$(cat docsearch.config.json | jq -r tostring)" \ 29 | typesense/docsearch-scraper:0.9.1 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.nyc_output/ 2 | /__codeorigin/ 3 | /coverage/ 4 | /demos/*/package-lock.json 5 | /demos/*/node_modules/ 6 | /demos/*/tmp/ 7 | /docs/.jekyll-cache/ 8 | /docs/_site/ 9 | /docs/Gemfile.lock 10 | /test/benchmark/package-lock.json 11 | /test/benchmark/node_modules/ 12 | /node_modules/ 13 | /qunit/ 14 | /temp/ 15 | /.eslintcache 16 | /package-lock.json 17 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | This project adheres to the [OpenJS Foundation Code of Conduct](https://code-of-conduct.openjsf.org/). 2 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security policy 2 | 3 | ## Supported versions 4 | 5 | The [latest release](https://qunitjs.com/#current-release) of QUnit is supported with security updates. 6 | 7 | ## Reporting a vulnerability 8 | 9 | If you discover a vulnerability, we would like to know about it so we can take steps to address it as quickly as possible. 10 | 11 | E-mail your findings to security@jquery.com. Thanks! 12 | -------------------------------------------------------------------------------- /build/browserstack-debug.json: -------------------------------------------------------------------------------- 1 | { 2 | "test_framework": "qunit", 3 | "test_path": ["test/index.html"], 4 | "test_server_port": "8899", 5 | "exit_with_fail": true, 6 | "timeout": 600, 7 | "browsers": [ 8 | "firefox_current", 9 | "chrome_current" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /build/browserstack-quick.json: -------------------------------------------------------------------------------- 1 | { 2 | "test_framework": "qunit", 3 | "test_path": ["test/index.html"], 4 | "test_server_port": "8899", 5 | "exit_with_fail": true, 6 | "timeout": 600, 7 | "browsers": [ 8 | "firefox_45", 9 | "firefox_current", 10 | "ie_9", 11 | "safari_9.1", 12 | "safari_current", 13 | "opera_current", 14 | "chrome_current", 15 | { 16 | "device": "Samsung Galaxy S20", 17 | "real_mobile": true, 18 | "os": "android", 19 | "os_version": "10.0" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /build/coverage-bridge.js: -------------------------------------------------------------------------------- 1 | /* global QUnit, window */ 2 | 3 | (function () { 4 | function sendMessage () { 5 | window.__grunt_contrib_qunit__.apply(window, arguments); 6 | } 7 | 8 | QUnit.on('runEnd', function () { 9 | // send coverage data if available 10 | if (window.__coverage__) { 11 | sendMessage('qunit.coverage', window.location.pathname, window.__coverage__); 12 | } 13 | }); 14 | }()); 15 | -------------------------------------------------------------------------------- /build/hydra-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": [ 3 | "2023-05: twitter.com serves broken redirect-loop", 4 | "2024-06: npmjs.com responds HTTP 429 Too Many Requests too easily", 5 | "2024-07: element.io and gitter.im chat rooms render fine but oddly use HTTP 404", 6 | "2025-01: github.com responds HTTP 429 Too Many Requests for the bulk of trivial links. We can probably keep a few other GitHub links.", 7 | "" 8 | ], 9 | "exclude_scheme_prefixes": [ 10 | "https://twitter.com/", 11 | "https://app.element.io/", 12 | "https://app.gitter.im/", 13 | "https://www.npmjs.com/package/", 14 | "https://github.com/qunitjs/qunit/issues/", 15 | "https://github.com/qunitjs/qunit/pull/", 16 | "https://github.com/qunitjs/qunit/blob/main/docs/_posts/" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /build/site-update-plugins.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const { keyword } = require('./npm-search.js'); 5 | 6 | (async function main () { 7 | let plugins = await keyword('qunit-plugin'); 8 | plugins = plugins.map((plugin) => ({ 9 | name: plugin.name, 10 | description: plugin.description, 11 | date: plugin.date 12 | })).sort((a, b) => a.name < b.name ? -1 : 1); 13 | fs.writeFileSync('./docs/_data/plugins.json', JSON.stringify(plugins, null, 2) + '\n'); 14 | console.log('Done!'); 15 | }()); 16 | -------------------------------------------------------------------------------- /demos/bundlers/README.md: -------------------------------------------------------------------------------- 1 | # QUnit ♥️ Rollup & Webpack 2 | 3 | See also and . 4 | 5 | ```bash 6 | npm run build 7 | npm test 8 | ``` 9 | 10 | ``` 11 | Running "qunit:all" (qunit) task 12 | Testing http://localhost:8000/test.html .OK 13 | >> passed test "example" 14 | >> 1 test completed in 0ms, with 0 failed, 0 skipped, and 0 todo. 15 | 16 | Done. 17 | ``` 18 | -------------------------------------------------------------------------------- /demos/bundlers/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/demos/bundlers/favicon.ico -------------------------------------------------------------------------------- /demos/bundlers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "@rollup/plugin-commonjs": "^26.0.1", 5 | "@rollup/plugin-node-resolve": "^15.2.3", 6 | "grunt": "1.6.1", 7 | "grunt-contrib-connect": "^5.0.0", 8 | "grunt-contrib-qunit": "10.1.1", 9 | "qunit": "file:../..", 10 | "rollup": "^4.18.0", 11 | "webpack": "^5.92.0" 12 | }, 13 | "scripts": { 14 | "build": "node build.mjs", 15 | "test": "grunt test" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /demos/bundlers/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es2020": true 4 | }, 5 | "parserOptions": { 6 | "ecmaVersion": 2020, 7 | "sourceType": "module" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /demos/bundlers/test/import-default.js: -------------------------------------------------------------------------------- 1 | import QUnit from 'qunit'; 2 | import { add } from './src.js'; 3 | 4 | (globalThis.TEST_OBJECTS || (globalThis.TEST_OBJECTS = {})).import_default = QUnit; 5 | 6 | QUnit.hello_import_default = QUnit.assert.hello_import_default = 'import-default'; 7 | 8 | QUnit.test('import-default', function (assert) { 9 | assert.equal(add(2, 3), 5); 10 | }); 11 | -------------------------------------------------------------------------------- /demos/bundlers/test/import-named.js: -------------------------------------------------------------------------------- 1 | import { QUnit, assert, test } from 'qunit'; 2 | import { add } from './src.js'; 3 | 4 | (globalThis.TEST_OBJECTS || (globalThis.TEST_OBJECTS = {})).import_named = QUnit; 5 | 6 | QUnit.hello_import_named = assert.hello_import_named = 'import-named'; 7 | 8 | test('import-named', function (assert) { 9 | assert.equal(add(2, 3), 5); 10 | }); 11 | -------------------------------------------------------------------------------- /demos/bundlers/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /demos/bundlers/test/require-default.cjs: -------------------------------------------------------------------------------- 1 | const QUnit = require('qunit'); 2 | const { add } = require('./src.js'); 3 | 4 | (globalThis.TEST_OBJECTS || (globalThis.TEST_OBJECTS = {})).require_default = QUnit; 5 | 6 | QUnit.hello_require_default = QUnit.assert.hello_require_default = 'require-default'; 7 | 8 | QUnit.test('require-default', function (assert) { 9 | assert.equal(add(2, 3), 5); 10 | }); 11 | -------------------------------------------------------------------------------- /demos/bundlers/test/require-sub.cjs: -------------------------------------------------------------------------------- 1 | const QUnit = require('qunit').QUnit; 2 | const { add } = require('./src.js'); 3 | 4 | (globalThis.TEST_OBJECTS || (globalThis.TEST_OBJECTS = {})).require_sub = QUnit; 5 | 6 | QUnit.hello_require_sub = QUnit.assert.hello_require_sub = 'require-sub'; 7 | 8 | QUnit.test('require-sub', function (assert) { 9 | assert.equal(add(2, 3), 5); 10 | }); 11 | -------------------------------------------------------------------------------- /demos/bundlers/test/src.js: -------------------------------------------------------------------------------- 1 | export function add (a, b) { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /demos/grunt-contrib-qunit/Gruntfile.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 'use strict'; 3 | module.exports = function (grunt) { 4 | grunt.loadNpmTasks('grunt-contrib-qunit'); 5 | 6 | grunt.initConfig({ 7 | qunit: { 8 | pass: ['pass-*.html'], 9 | 'fail-assert': 'fail-assert.html', 10 | 'fail-no-tests': 'fail-no-tests.html', 11 | 'fail-uncaught': 'fail-uncaught.html' 12 | } 13 | }); 14 | 15 | grunt.registerTask('default', ['qunit:pass']); 16 | }; 17 | -------------------------------------------------------------------------------- /demos/grunt-contrib-qunit/README.md: -------------------------------------------------------------------------------- 1 | # QUnit ♥️ Grunt 2 | 3 | See also . 4 | 5 | ```bash 6 | npm test 7 | ``` 8 | 9 | ``` 10 | Running "qunit:example" (qunit) task 11 | Testing test/example.html ..OK 12 | ``` 13 | -------------------------------------------------------------------------------- /demos/grunt-contrib-qunit/fail-assert.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QUnit 6 | 7 | 8 | 9 |
10 | 11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /demos/grunt-contrib-qunit/fail-no-tests.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QUnit 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /demos/grunt-contrib-qunit/fail-uncaught.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QUnit 6 | 7 | 8 | 9 |
10 | 11 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /demos/grunt-contrib-qunit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "grunt": "1.6.1", 5 | "grunt-contrib-qunit": "10.1.1" 6 | }, 7 | "scripts": { 8 | "test": "grunt" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /demos/grunt-contrib-qunit/pass-basic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QUnit 6 | 7 | 8 | 9 |
10 | 11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /demos/grunt-contrib-qunit/qunit: -------------------------------------------------------------------------------- 1 | ../../qunit -------------------------------------------------------------------------------- /demos/karma-qunit/README.md: -------------------------------------------------------------------------------- 1 | # QUnit ♥️ Karma 2 | 3 | See also and . 4 | 5 | ```bash 6 | npm test 7 | ``` 8 | 9 | ``` 10 | INFO [karma-server]: Karma server started 11 | INFO [launcher]: Starting browser FirefoxHeadless 12 | INFO [Firefox]: Connected on socket 13 | ... 14 | Firefox: Executed 3 of 3 SUCCESS 15 | ``` 16 | -------------------------------------------------------------------------------- /demos/karma-qunit/fail-assert.js: -------------------------------------------------------------------------------- 1 | QUnit.test('example', function (assert) { 2 | assert.true(false, 'some message'); 3 | }); 4 | -------------------------------------------------------------------------------- /demos/karma-qunit/fail-global-error.js: -------------------------------------------------------------------------------- 1 | QUnit.test('example', function (assert) { 2 | // eslint-disable-next-line no-undef 3 | boom(); 4 | assert.true(true); 5 | }); 6 | -------------------------------------------------------------------------------- /demos/karma-qunit/karma.conf.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | module.exports = function (config) { 4 | config.set({ 5 | browsers: [ 6 | 'FirefoxHeadless' 7 | ], 8 | client: process.env.KARMA_QUNIT_CONFIG 9 | ? { 10 | qunit: { 11 | testTimeout: 1991, 12 | fooBar: 'xyz' 13 | } 14 | } 15 | : {}, 16 | frameworks: ['qunit'], 17 | files: [ 18 | process.env.KARMA_FILES || 'pass-basic.js' 19 | ], 20 | autoWatch: false, 21 | singleRun: true, 22 | reporters: ['dots'] 23 | }); 24 | }; 25 | -------------------------------------------------------------------------------- /demos/karma-qunit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "karma": "^6.4.2", 5 | "karma-chrome-launcher": "^3.2.0", 6 | "karma-firefox-launcher": "2.1.3", 7 | "karma-qunit": "^4.2.0", 8 | "qunit": "file:../.." 9 | }, 10 | "scripts": { 11 | "test": "karma start --no-colors" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /demos/karma-qunit/pass-basic.js: -------------------------------------------------------------------------------- 1 | QUnit.test('example 1', function (assert) { 2 | assert.true(true, 'x'); 3 | }); 4 | QUnit.test('example 2', function (assert) { 5 | assert.true(true, 'y'); 6 | }); 7 | QUnit.test('example 3', function (assert) { 8 | assert.true(true, 'z'); 9 | }); 10 | -------------------------------------------------------------------------------- /demos/karma-qunit/pass-config.js: -------------------------------------------------------------------------------- 1 | QUnit.test('set config', function (assert) { 2 | assert.strictEqual(QUnit.config.testTimeout, 1991, 'testTimeout'); 3 | assert.strictEqual(QUnit.config.fooBar, 'xyz', 'fooBar'); 4 | }); 5 | -------------------------------------------------------------------------------- /demos/nyc/.gitignore: -------------------------------------------------------------------------------- 1 | /.nyc_output/ 2 | /coverage/ 3 | /node_modules/ 4 | -------------------------------------------------------------------------------- /demos/nyc/README.md: -------------------------------------------------------------------------------- 1 | # QUnit ♥️ Istanbul 2 | 3 | See also . 4 | 5 | ```bash 6 | npm test 7 | ``` 8 | 9 | ``` 10 | TAP version 13 11 | ok 1 add > two numbers 12 | 1..1 13 | # pass 1 14 | # skip 0 15 | # todo 0 16 | # fail 0 17 | --------------|---------|----------|---------|---------|------------------- 18 | File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 19 | --------------|---------|----------|---------|---------|------------------- 20 | All files | 85.71 | 100 | 50 | 85.71 | 21 | nyc | 100 | 100 | 100 | 100 | 22 | index.js | 100 | 100 | 100 | 100 | 23 | nyc/src | 75 | 100 | 50 | 75 | 24 | add.js | 100 | 100 | 100 | 100 | 25 | subtract.js | 50 | 100 | 0 | 50 | 2 26 | --------------|---------|----------|---------|---------|------------------- 27 | ``` 28 | -------------------------------------------------------------------------------- /demos/nyc/index.js: -------------------------------------------------------------------------------- 1 | const add = require('./src/add.js'); 2 | const subtract = require('./src/subtract.js'); 3 | 4 | module.exports = { 5 | add, 6 | subtract 7 | }; 8 | -------------------------------------------------------------------------------- /demos/nyc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "nyc": "15.1.0", 5 | "qunit": "file:../.." 6 | }, 7 | "scripts": { 8 | "test": "nyc qunit" 9 | }, 10 | "nyc": { 11 | "exclude": [ 12 | "test/" 13 | ], 14 | "report-dir": "coverage/", 15 | "reporter": [ 16 | "text", 17 | "html", 18 | "lcov" 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /demos/nyc/src/add.js: -------------------------------------------------------------------------------- 1 | function add (a, b) { 2 | return a + b; 3 | } 4 | 5 | module.exports = add; 6 | -------------------------------------------------------------------------------- /demos/nyc/src/subtract.js: -------------------------------------------------------------------------------- 1 | function substract (a, b) { 2 | return a - b; 3 | } 4 | 5 | module.exports = substract; 6 | -------------------------------------------------------------------------------- /demos/nyc/test/add.js: -------------------------------------------------------------------------------- 1 | const add = require('../index.js').add; 2 | 3 | QUnit.module('add', () => { 4 | QUnit.test('two numbers', assert => { 5 | assert.equal(add(1, 2), 3); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /demos/q4000-qunit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | q4000 on QUnit 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /demos/qunit-config-maxDepth.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | qunit-config-maxDepth 6 | 7 | 8 | 9 |
10 | 11 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /demos/qunit-onerror-early.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | window-onerror-early 6 | 7 | 8 | 20 | 25 | 26 | 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /demos/testem.js: -------------------------------------------------------------------------------- 1 | const cp = require('child_process'); 2 | const path = require('path'); 3 | const DIR = path.join(__dirname, 'testem'); 4 | 5 | function normalize (str) { 6 | return str 7 | .trim() 8 | .replace(/(Firefox) [\d.]+/g, '$1') 9 | .replace(/(\d+ ms)/g, '0 ms'); 10 | } 11 | 12 | // Fast re-runs 13 | process.env.npm_config_prefer_offline = 'true'; 14 | process.env.npm_config_update_notifier = 'false'; 15 | process.env.npm_config_audit = 'false'; 16 | 17 | QUnit.module('testem', { 18 | before: () => { 19 | cp.execSync('npm install', { cwd: DIR, encoding: 'utf8' }); 20 | } 21 | }); 22 | 23 | QUnit.test('passing test', assert => { 24 | const ret = cp.execSync('npm run -s test', { cwd: DIR, encoding: 'utf8' }); 25 | assert.strictEqual( 26 | normalize(ret), 27 | ` 28 | ok 1 Firefox - [0 ms] - add: two numbers 29 | 30 | 1..1 31 | # tests 1 32 | # pass 1 33 | # skip 0 34 | # todo 0 35 | # fail 0 36 | 37 | # ok 38 | `.trim() 39 | ); 40 | }); 41 | -------------------------------------------------------------------------------- /demos/testem/README.md: -------------------------------------------------------------------------------- 1 | # QUnit ♥️ Testem 2 | 3 | See also . 4 | 5 | ```bash 6 | npm test 7 | ``` 8 | 9 | ``` 10 | ok 1 Firefox - [0 ms] - add: two numbers 11 | 12 | 1..1 13 | # tests 1 14 | # pass 1 15 | # skip 0 16 | # todo 0 17 | # fail 0 18 | 19 | # ok 20 | ``` 21 | -------------------------------------------------------------------------------- /demos/testem/add.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | 3 | function add (a, b) { 4 | return a + b; 5 | } 6 | -------------------------------------------------------------------------------- /demos/testem/add.test.js: -------------------------------------------------------------------------------- 1 | /* global add */ 2 | QUnit.module('add', () => { 3 | QUnit.test('two numbers', assert => { 4 | assert.equal(add(1, 2), 3); 5 | }); 6 | }); 7 | -------------------------------------------------------------------------------- /demos/testem/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "testem": "3.13.0" 5 | }, 6 | "scripts": { 7 | "test": "testem -l 'Headless Firefox' ci" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /demos/testem/qunit: -------------------------------------------------------------------------------- 1 | ../../qunit -------------------------------------------------------------------------------- /demos/testem/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Testem 5 | 6 | 7 | 8 | 9 | 10 | 14 | 15 | 16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /demos/testem/testem.json: -------------------------------------------------------------------------------- 1 | { 2 | "framework": "qunit", 3 | "test_page": "test.html" 4 | } 5 | -------------------------------------------------------------------------------- /docs/404.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: Page not found 4 | permalink: /404.html 5 | --- 6 | 7 |

It seems we can't find what you're looking for.

8 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | qunitjs.com 2 | -------------------------------------------------------------------------------- /docs/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | ruby RUBY_VERSION 3 | 4 | # To apply changes, run `bundle update`. 5 | gem "jekyll-theme-amethyst", "2.8.2", group: :jekyll_plugins 6 | -------------------------------------------------------------------------------- /docs/_data/authors.yaml: -------------------------------------------------------------------------------- 1 | jzaefferer: Jörn Zaefferer 2 | jamesmgreene: James M. Greene 3 | leobalter: Leo Balter 4 | trentmwillis: Trent Willis 5 | krinkle: Timo Tijhof 6 | -------------------------------------------------------------------------------- /docs/_data/sidebar_api.yml: -------------------------------------------------------------------------------- 1 | - group: main 2 | expand: initial 3 | initial: /api/ 4 | 5 | - group: assert 6 | 7 | - group: callbacks 8 | 9 | - group: async 10 | # These pages are all in at least one other group. 11 | # It exists for discoverability, but we don't need 12 | # to highlight its pages in two places. 13 | expand: false 14 | 15 | - title: Configuration 16 | group: config 17 | 18 | - title: Reporters 19 | group: reporters 20 | 21 | - group: extension 22 | 23 | - group: deprecated 24 | expand: false 25 | 26 | - group: removed 27 | expand: false 28 | -------------------------------------------------------------------------------- /docs/_data/sidebar_blog.yml: -------------------------------------------------------------------------------- 1 | - type: recent 2 | title: Recent blog posts 3 | expand: true 4 | 5 | - type: tags 6 | title: Tags 7 | expand: true 8 | 9 | - type: archive 10 | title: Archives 11 | expand: true 12 | -------------------------------------------------------------------------------- /docs/_data/sitenav.yml: -------------------------------------------------------------------------------- 1 | - name: Guides 2 | href: /guides/ 3 | sub: 4 | - name: Getting Started 5 | href: /intro/ 6 | - name: Download 7 | href: /intro/#download 8 | - name: Browser Runner 9 | href: /browser/ 10 | - name: Command-line Interface 11 | href: /cli/ 12 | - name: Compatibility 13 | href: /intro/#compatibility 14 | - name: Test lifecycle 15 | href: /lifecycle/ 16 | - name: QUnit 2.0 Upgrade Guide 17 | href: /upgrade-guide-2.x/ 18 | - name: Documentation 19 | href: /api/ 20 | - name: Blog 21 | href: /blog/ 22 | - name: Community 23 | href: /about/ 24 | sub: 25 | - name: Support & Chat 26 | href: /intro/#support 27 | - name: Plugins 28 | href: /plugins/ 29 | - name: Who's using QUnit? 30 | href: /projects/ 31 | - name: About QUnit 32 | href: /about/ 33 | - name: Badge 34 | href: /badge/ 35 | - name: Brand Guidelines 36 | href: /brand/ 37 | -------------------------------------------------------------------------------- /docs/_posts/2011-10-06-qunit-1-0-0.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "QUnit 1.0.0 Released" 4 | author: jzaefferer 5 | tags: 6 | - release 7 | --- 8 | 9 | First stable release. 10 | 11 | ## See also 12 | 13 | * [Git tag: 1.0.0](https://github.com/qunitjs/qunit/releases/tag/1.0.0) 14 | -------------------------------------------------------------------------------- /docs/_posts/2011-11-24-qunit-1-2-0.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "QUnit 1.2.0 Released" 4 | author: jzaefferer 5 | tags: 6 | - release 7 | --- 8 | 9 | Support in `deepEqual` for comparing null objects via object literals, and various bug fixes. 10 | 11 | ## Changelog 12 | 13 | * Assert: Allow [`deepEqual`](https://qunitjs.com/api/assert/deepEqual/) to test objects with null prototype against object literals. (Domenic Denicola) [#170](https://github.com/qunitjs/qunit/pull/170) 14 | * Core: Fix IE8 "Member not found" error. (Jimmy Mabey) [#154](https://github.com/qunitjs/qunit/issues/154) 15 | * Core: Fix internal `start()` call to use `QUnit.start()`, since global is not exported in CommonJS runtimes, such as Node.js. (Antoine Musso) [#168](https://github.com/qunitjs/qunit/pull/168) 16 | 17 | ## See also 18 | 19 | * [Git tag: 1.2.0](https://github.com/qunitjs/qunit/releases/tag/1.2.0) 20 | 21 | -------------------------------------------------------------------------------- /docs/_posts/2012-04-04-qunit-1-5-0.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "QUnit 1.5.0 Released" 4 | author: jzaefferer 5 | tags: 6 | - release 7 | --- 8 | 9 | ## Changelog 10 | 11 | * Addons/JUnitLogger: Add `results` data to `QUnit.jUnitReport` callback argument. The function accepts one argument shaped as `{ xml: ' { 35 | console.log(`Now running: ${details.name}`); 36 | }); 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/api/callbacks/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: group 3 | group: callbacks 4 | title: Callback events 5 | redirect_from: 6 | - "/callbacks/" 7 | - "/category/callbacks/" 8 | --- 9 | -------------------------------------------------------------------------------- /docs/api/config/altertitle.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-api 3 | title: QUnit.config.altertitle 4 | excerpt: Insert a success or failure symbol in the document title. 5 | groups: 6 | - config 7 | redirect_from: 8 | - "/config/altertitle/" 9 | version_added: "1.0.0" 10 | --- 11 | 12 | In browser environments, whether to insert a success or failure symbol in the document title. 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
type`boolean`
default`true`
24 | 25 | By default, QUnit updates `document.title` to insert a checkmark or cross symbol to indicate whether the test run passed or failed. This helps quickly spot from the tab bar whether a run passed, without opening it. 26 | 27 | If you're integration-testing code that makes changes to `document.title`, or otherwise conflicts with this feature, you can disable it. 28 | -------------------------------------------------------------------------------- /docs/api/config/collapse.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-api 3 | title: QUnit.config.collapse 4 | excerpt: Collapse the details of failing tests after the first one (HTML Reporter). 5 | groups: 6 | - config 7 | redirect_from: 8 | - "/config/collapse/" 9 | version_added: "1.0.0" 10 | --- 11 | 12 | In the HTML Reporter, collapse the details of failing tests after the first one. 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
type`boolean`
default`true`
24 | 25 | By default, the [HTML Reporter](../../browser.md) collapses consecutive failing tests showing only the details for the first failed test. The other tests can be expanded manually with a single click on the test title. 26 | 27 | Set this option to `false` to expand the details for all failing tests. 28 | -------------------------------------------------------------------------------- /docs/api/config/failOnZeroTests.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-api 3 | title: QUnit.config.failOnZeroTests 4 | excerpt: Fail the test run if no tests were run. 5 | groups: 6 | - config 7 | redirect_from: 8 | - "/config/failOnZeroTests/" 9 | version_added: "2.16.0" 10 | --- 11 | 12 | Whether to fail the test run if no tests were run. 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
type`boolean`
default`true`
24 | 25 | By default, it is considered an error if no tests were loaded, or if no tests matched the current filter. 26 | 27 | Set this option to `false` to let an empty test run result in a success instead. 28 | -------------------------------------------------------------------------------- /docs/api/config/hidepassed.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-api 3 | title: QUnit.config.hidepassed 4 | excerpt: Hide results of passed tests (HTML Reporter). 5 | groups: 6 | - config 7 | redirect_from: 8 | - "/config/hidepassed/" 9 | version_added: "1.0.0" 10 | --- 11 | 12 | In the HTML Reporter, hide results of passed tests. 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
type`boolean`
default`false`
24 | 25 |

26 | 27 | This option can also be controlled via the [HTML Reporter](../../browser.md). 28 | 29 |

30 | 31 | By default, the HTML Reporter will list both passing and failing tests. Passing tests are by default collapsed to display only their name. Enable `hidepassed` to hide passing tests completely, and show only failing tests in the list. 32 | 33 | ## See also 34 | 35 | * [QUnit.config.collapse](./collapse.md) 36 | -------------------------------------------------------------------------------- /docs/api/config/moduleId.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-api 3 | title: QUnit.config.moduleId 4 | excerpt: Select one or more modules to run, by their internal ID (HTML Reporter). 5 | groups: 6 | - config 7 | redirect_from: 8 | - "/config/moduleId/" 9 | version_added: "1.23.0" 10 | --- 11 | 12 | Used by the HTML Reporter, this selects one or more modules by their internal ID to run exclusively. 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
type`array` or `undefined`
default`undefined`
24 | 25 |

26 | 27 | This option can be controlled via the [HTML Reporter](../../browser.md) interface. 28 | 29 |

30 | 31 | Specify modules by their internally hashed identifier for a given module. You can specify one or multiple modules to run. This option powers the multi-select dropdown menu in the HTML Reporter. 32 | 33 | See also: 34 | * [QUnit.config.module](./module.md) 35 | * [QUnit.config.testId](./testId.md) 36 | -------------------------------------------------------------------------------- /docs/api/config/reporters.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-api 3 | title: QUnit.config.reporters 4 | excerpt: Control which reporters to enable or disable. 5 | groups: 6 | - config 7 | redirect_from: 8 | - "/config/reporters/" 9 | version_added: "2.24.0" 10 | --- 11 | 12 | Control which reporters to enable or disable. 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
type`Object`
default`{}`
24 | 25 | ## Built-in reporters 26 | 27 | * [`tap`](../reporters/tap.md) 28 | * [`console`](../reporters/console.md) 29 | * [`perf`](../reporters/perf.md) 30 | * [`html`](../reporters/html.md) 31 | 32 | ## Example 33 | 34 | Enable TAP in the browser via [preconfig](./index.md#preconfiguration): 35 | ```js 36 | // Set as global variable before loading qunit.js 37 | qunit_config_reporters_tap = true; 38 | ``` 39 | 40 | Or, via [QUnit.config](../config/index.md): 41 | 42 | ```js 43 | // Set from any inline script or JS file after qunit.js 44 | QUnit.config.reporters.tap = true; 45 | ``` 46 | -------------------------------------------------------------------------------- /docs/api/config/requireExpects.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-api 3 | title: QUnit.config.requireExpects 4 | excerpt: Fail tests that don't specify how many assertions they expect. 5 | groups: 6 | - config 7 | redirect_from: 8 | - "/config/requireExpects/" 9 | version_added: "1.7.0" 10 | --- 11 | 12 | Fail tests that don't specify how many assertions they expect. 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
type`boolean`
default`false`
24 | 25 | Enabling this option will cause tests to fail if they don't call [`assert.expect()`](../assert/expect.md). 26 | -------------------------------------------------------------------------------- /docs/api/config/scrolltop.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-api 3 | title: QUnit.config.scrolltop 4 | excerpt: Scroll to the top of the page after the test run. 5 | groups: 6 | - config 7 | redirect_from: 8 | - "/config/scrolltop/" 9 | version_added: "1.14.0" 10 | --- 11 | 12 | In browser environments, scroll to the top of the page after the tests are done. 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
type`boolean`
default`true`
24 | 25 | By default, QUnit scrolls the browser to the top of the page when tests are done. This reverses any programmatic scrolling performed by the application or its tests. 26 | 27 | Set this option to `false` to disable this behaviour, and thus leave the page in its final scroll position. 28 | -------------------------------------------------------------------------------- /docs/api/config/testId.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-api 3 | title: QUnit.config.testId 4 | excerpt: Select one or more tests to run, by their internal ID (HTML Reporter). 5 | groups: 6 | - config 7 | redirect_from: 8 | - "/config/testId/" 9 | version_added: "1.16.0" 10 | --- 11 | 12 | Used by the HTML Reporter, select one or more tests to run by their internal ID. 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
type`array` or `undefined`
default`undefined`
24 | 25 |

26 | 27 | This option can be controlled via the [HTML Reporter](../../browser.md) interface. 28 | 29 |

30 | 31 | This property allows QUnit to run specific tests by their internally hashed identifier. You can specify one or multiple tests to run. This option powers the "Rerun" button in the HTML Reporter. 32 | 33 | See also: 34 | * [QUnit.config.filter](./filter.md) 35 | * [QUnit.config.moduleId](./moduleId.md) 36 | -------------------------------------------------------------------------------- /docs/api/deprecated.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: group 3 | group: deprecated 4 | title: Deprecated methods 5 | redirect_from: 6 | - "/deprecated/" 7 | --- 8 | -------------------------------------------------------------------------------- /docs/api/extension/QUnit.assert.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-api 3 | title: QUnit.assert 4 | excerpt: Namespace for QUnit assertion methods. 5 | groups: 6 | - extension 7 | redirect_from: 8 | - "/config/QUnit.assert/" 9 | - "/extension/QUnit.assert/" 10 | version_added: "1.7.0" 11 | --- 12 | 13 | Namespace for QUnit assertion methods. This object is the prototype for the internal Assert class of which instances are passed as the argument to [`QUnit.test()`](../QUnit/test.md) callbacks. 14 | 15 | This object contains QUnit's [built-in assertion methods](../assert/index.md), and may be extended by plugins to register additional assertion methods. 16 | 17 | See [`assert.pushResult()`](../assert/pushResult.md) for how to create a custom assertion. 18 | -------------------------------------------------------------------------------- /docs/api/extension/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: group 3 | group: extension 4 | title: Extension interface 5 | redirect_from: 6 | - "/extension/" 7 | --- 8 | -------------------------------------------------------------------------------- /docs/api/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page-api 3 | title: QUnit API 4 | excerpt: API reference documentation for QUnit. 5 | amethyst: 6 | prepend_description_heading: false 7 | redirect_from: 8 | - "/category/all/" 9 | --- 10 | 11 | If you're new to QUnit, check out [Getting Started](../intro.md)! 12 | 13 | QUnit is a powerful, easy-to-use JavaScript unit test suite. QUnit has no dependencies and supports Node.js, SpiderMonkey, and all [major browsers](../intro.md#compatibility). 14 | 15 | 16 | 17 | * [Main methods](./QUnit/) 18 | * [Assertions](./assert/) 19 | * [Callback events](./callbacks/) 20 | * [Configuration options](./config/) 21 | * [Reporters](./reporters/) 22 | * [Extension interface](./extension/) 23 | -------------------------------------------------------------------------------- /docs/api/removed.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: group 3 | group: removed 4 | title: Removed methods 5 | redirect_from: 6 | - "/removed/" 7 | --- 8 | -------------------------------------------------------------------------------- /docs/api/reporters/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: group 3 | group: reporters 4 | title: QUnit.reporters 5 | excerpt: Built-in reporters for TAP, HTML, console, and perf. 6 | amethyst: 7 | # Override inherited "pagetype: navigation" to enable Typesense indexing 8 | pagetype: custom 9 | robots: index 10 | --- 11 | 12 | To create your own reporter, refer to the [QUnit.on()](../callbacks/QUnit.on.md) event emitter and its Reporter API. 13 | -------------------------------------------------------------------------------- /docs/badge.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: Tested with QUnit Badge 4 | --- 5 | 6 |

Use the following markup to embed a "Tested with QUnit" badge in your documentation.

7 | 8 | [![Tested with QUnit](./testedwith.svg)](/) 9 | 10 | Copy the Markdown snippet, and e.g. paste above the title your README. 11 | 12 | ```md 13 | [![Tested with QUnit](https://qunitjs.com/testedwith.svg)](https://qunitjs.com/) 14 | ``` 15 | 16 | HTML version: 17 | 18 | ```html 19 | Tested with QUnit 20 | ``` 21 | -------------------------------------------------------------------------------- /docs/blog.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: posts 3 | title: QUnit Blog 4 | --- 5 | -------------------------------------------------------------------------------- /docs/blog/archive.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: posts-archive 3 | title: Archive 4 | --- 5 | 6 | 21 | -------------------------------------------------------------------------------- /docs/blog/tag/feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: posts-tag 3 | tag: feature 4 | title: Feature 5 | --- 6 | -------------------------------------------------------------------------------- /docs/blog/tag/release.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: posts-tag 3 | tag: release 4 | title: Release 5 | --- 6 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/favicon.ico -------------------------------------------------------------------------------- /docs/img/2011-logo-qunit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/img/2011-logo-qunit.png -------------------------------------------------------------------------------- /docs/img/2012-logo-qunit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/img/2012-logo-qunit.png -------------------------------------------------------------------------------- /docs/img/2012-logo-qunit@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/img/2012-logo-qunit@2x.png -------------------------------------------------------------------------------- /docs/img/2012-website-qunit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/img/2012-website-qunit.png -------------------------------------------------------------------------------- /docs/img/2012b-logo-qunit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/img/2012b-logo-qunit.png -------------------------------------------------------------------------------- /docs/img/2013-logo-qunit_color_study.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/img/2013-logo-qunit_color_study.png -------------------------------------------------------------------------------- /docs/img/2013-website-qunit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/img/2013-website-qunit.png -------------------------------------------------------------------------------- /docs/img/2020-website-qunit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/img/2020-website-qunit.png -------------------------------------------------------------------------------- /docs/img/QUnit-Logo-Large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/img/QUnit-Logo-Large.png -------------------------------------------------------------------------------- /docs/img/logo-qunit@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/img/logo-qunit@2x.png -------------------------------------------------------------------------------- /docs/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/img/logo.png -------------------------------------------------------------------------------- /docs/plugins.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: Plugins 4 | redirect_from: 5 | - "/addons/" 6 | --- 7 | 8 |

Plugins can extend, enhance, and modify QUnit itself; as well as the developer experience of using QUnit.

9 | 10 |
    11 | {% assign _plugins = site.data.plugins | sort: "date" | reverse -%} 12 | {%- for plugin in _plugins -%} 13 |
  • 14 |

    {{ plugin.name }}

    15 |

    {{ plugin.description }}

    16 |
  • 17 | {% endfor %} 18 |
19 | 20 | Plugins are sometimes known as QUnit addons. 21 | 22 | _Note: This list is automatically generated from npm packages using the [**qunit-plugin** keyword](https://www.npmjs.com/search?q=keywords:qunit-plugin)._ 23 | -------------------------------------------------------------------------------- /docs/projects.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: Who's using QUnit? 4 | --- 5 | 6 |

These organizations and open-source projects, and many others, use QUnit to keep their code in check.

7 | 8 | ## Organizations 9 | 10 |
11 | {% assign entries = site.data.projects.orgs | sort_natural: "name" -%} 12 | {%- for entry in entries -%} 13 |
14 | ### [{{ entry.name }}]({{ entry.href }}) 15 | {%- for sub in entry.sub %} 16 | [{{ sub.name }}]({{ sub.href }}){% if entry.sub.last != sub %}, {% endif %} 17 | {%- endfor %} 18 |
19 | {% endfor %} 20 |
21 |
22 | 23 | ## Projects 24 | 25 |
26 | {% assign entries = site.data.projects.projects | sort_natural: "name" -%} 27 | {%- for entry in entries -%} 28 |
29 | ### [{{ entry.name }}]({{ entry.href }}) 30 | {%- for sub in entry.sub %} 31 | [{{ sub.name }}]({{ sub.href }}){% if entry.sub.last != sub %}, {% endif %} 32 | {%- endfor %} 33 |
34 | {% endfor %} 35 |
36 | -------------------------------------------------------------------------------- /docs/resources/2025-stacktrace-assert-html.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/resources/2025-stacktrace-assert-html.png -------------------------------------------------------------------------------- /docs/resources/2025-stacktrace-assert-tap-after.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/resources/2025-stacktrace-assert-tap-after.png -------------------------------------------------------------------------------- /docs/resources/2025-stacktrace-assert-tap-before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/resources/2025-stacktrace-assert-tap-before.png -------------------------------------------------------------------------------- /docs/resources/2025-stacktrace-error-after.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/resources/2025-stacktrace-error-after.png -------------------------------------------------------------------------------- /docs/resources/2025-stacktrace-error-before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/resources/2025-stacktrace-error-before.png -------------------------------------------------------------------------------- /docs/resources/calc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * calc.js - An example project to demonstrate QUnit. 3 | * 4 | * @author Timo Tijhof, 2022 5 | * @license 0BSD 6 | * @license Public domain 7 | */ 8 | 9 | /** 10 | * @param {number} a 11 | * @param {number} b 12 | * @return {number} 13 | */ 14 | export function add (a, b) { 15 | return a + b; 16 | } 17 | 18 | /** 19 | * @param {number} a 20 | * @param {number} b 21 | * @return {number} 22 | */ 23 | export function substract (a, b) { 24 | return a - b; 25 | } 26 | 27 | /** 28 | * @param {number} a 29 | * @param {number} b 30 | * @return {number} 31 | */ 32 | export function multiply (a, b) { 33 | return a * b; 34 | } 35 | 36 | /** 37 | * @param {number} x 38 | * @return {number} 39 | */ 40 | export function square (x) { 41 | return x * x; 42 | } 43 | -------------------------------------------------------------------------------- /docs/resources/calc.test.js: -------------------------------------------------------------------------------- 1 | import * as calc from './calc.js'; 2 | 3 | QUnit.module('calc', () => { 4 | QUnit.test('add', (assert) => { 5 | assert.equal(calc.add(1, 2), 3); 6 | assert.equal(calc.add(2, 3), 5); 7 | assert.equal(calc.add(5, -1), 4, 'negative'); 8 | }); 9 | 10 | QUnit.test('substract', (assert) => { 11 | assert.equal(calc.substract(3, 2), 1); 12 | assert.equal(calc.substract(5, 3), 2); 13 | assert.equal(calc.substract(5, -1), 6, 'negative'); 14 | }); 15 | 16 | QUnit.test('multiply', (assert) => { 17 | assert.equal(calc.multiply(7, 2), 14); 18 | }); 19 | 20 | QUnit.test('square', (assert) => { 21 | assert.equal(calc.square(5), 25); 22 | assert.equal(calc.square(7), 49); 23 | assert.equal(calc.square(-8), 64, 'negative'); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /docs/resources/example-add.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | QUnit 5 | 6 | 7 |
8 |
9 | 10 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/resources/example-fail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | QUnit 5 | 6 | 7 |
8 |
9 | 10 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/resources/example-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | QUnit 5 | 6 | 7 |
8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/resources/perf-chrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/resources/perf-chrome.png -------------------------------------------------------------------------------- /docs/resources/perf-firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunitjs/qunit/4955dd930e8445a3db46648e7fed396857578e04/docs/resources/perf-firefox.png -------------------------------------------------------------------------------- /docsearch.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "index_name": "qunitjs_com", 3 | "start_urls": [ 4 | { "url": "https://qunitjs.com/blog/", "selectors_key": "blog", "page_rank": 1 }, 5 | { "url": "https://qunitjs.com", "page_rank": 20 } 6 | ], 7 | "selectors": { 8 | "lvl0": "h1", 9 | "lvl1": "h2:not(.screen-reader-text)", 10 | "lvl2": "h3:not(.screen-reader-text)", 11 | "lvl3": "h4:not(.screen-reader-text)", 12 | "lvl4": "h5:not(.screen-reader-text)", 13 | "lvl5": "h6:not(.screen-reader-text)", 14 | "text": ".content p, .content li, .content tr, .content pre" 15 | }, 16 | "custom_settings": { 17 | "token_separators": ["_", "-", "."] 18 | }, 19 | "selectors_exclude": [ 20 | ".posts", 21 | "aside.sidebar", 22 | ".toc-wrapper" 23 | ], 24 | "scrape_start_urls": false 25 | } 26 | -------------------------------------------------------------------------------- /src/cli/require-from-cwd.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function requireFromCWD (mod) { 4 | const resolvedPath = require.resolve(mod, { paths: [process.cwd()] }); 5 | return require(resolvedPath); 6 | }; 7 | -------------------------------------------------------------------------------- /src/core/hooks.js: -------------------------------------------------------------------------------- 1 | import config from './config.js'; 2 | 3 | function makeAddGlobalHook (hookName) { 4 | return function addGlobalHook (callback) { 5 | if (!config._globalHooks[hookName]) { 6 | config._globalHooks[hookName] = []; 7 | } 8 | config._globalHooks[hookName].push(callback); 9 | }; 10 | } 11 | 12 | export default { 13 | beforeEach: makeAddGlobalHook('beforeEach'), 14 | afterEach: makeAddGlobalHook('afterEach') 15 | }; 16 | -------------------------------------------------------------------------------- /src/core/logger.js: -------------------------------------------------------------------------------- 1 | import { console } from './globals.js'; 2 | 3 | // Support IE 9: No console object, unless the developer tools are not open. 4 | 5 | // Support IE 9: Function#bind is supported, but no console.log.bind(). 6 | 7 | // Support: SpiderMonkey (mozjs 68+) 8 | // The console object has a log method, but no warn method. 9 | 10 | export default { 11 | warn: console 12 | ? Function.prototype.bind.call(console.warn || console.log, console) 13 | : function () {} 14 | }; 15 | -------------------------------------------------------------------------------- /src/core/promise.js: -------------------------------------------------------------------------------- 1 | import _Promise from '../../lib/promise-polyfill.js'; 2 | 3 | export default _Promise; 4 | -------------------------------------------------------------------------------- /src/core/qunit-commonjs.js: -------------------------------------------------------------------------------- 1 | /* global module, exports */ 2 | import QUnit from './qunit.js'; 3 | 4 | // For Node.js 5 | if (typeof module !== 'undefined' && module && module.exports) { 6 | module.exports = QUnit; 7 | } 8 | 9 | // For CommonJS with exports, but without module.exports, like Rhino 10 | if (typeof exports !== 'undefined' && exports) { 11 | exports.QUnit = QUnit; 12 | } 13 | -------------------------------------------------------------------------------- /src/core/qunit-wrapper-bundler-require.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | // In a single bundler invocation, if different parts or dependencies 4 | // of a project mix ESM and CJS, avoid a split-brain state by making 5 | // sure both import and re-use the same instance via this wrapper. 6 | // 7 | // Bundlers generally allow requiring an ESM file from CommonJS. 8 | const { QUnit } = require('./esm/qunit.module.js'); 9 | module.exports = QUnit; 10 | -------------------------------------------------------------------------------- /src/core/qunit-wrapper-nodejs-module.js: -------------------------------------------------------------------------------- 1 | // In a single Node.js process, if different parts or dependencies 2 | // of a project mix ESM and CJS, avoid a split-brain state by making 3 | // sure both import and re-use the same instance via this wrapper. 4 | // 5 | // Node.js 12+ can import a CommonJS file from ESM. 6 | import QUnit from '../qunit.js'; 7 | 8 | export const { 9 | assert, 10 | begin, 11 | config, 12 | diff, 13 | done, 14 | dump, 15 | equiv, 16 | hooks, 17 | is, 18 | isLocal, 19 | log, 20 | module, 21 | moduleDone, 22 | moduleStart, 23 | objectType, 24 | on, 25 | only, 26 | onUncaughtException, 27 | pushFailure, 28 | reporters, 29 | skip, 30 | stack, 31 | start, 32 | test, 33 | testDone, 34 | testStart, 35 | todo, 36 | urlParams, 37 | version 38 | } = QUnit; 39 | 40 | export { QUnit }; 41 | 42 | export default QUnit; 43 | -------------------------------------------------------------------------------- /src/core/reporters.js: -------------------------------------------------------------------------------- 1 | import ConsoleReporter from './reporters/ConsoleReporter.js'; 2 | import PerfReporter from './reporters/PerfReporter.js'; 3 | import TapReporter from './reporters/TapReporter.js'; 4 | import HtmlReporter from './reporters/HtmlReporter.js'; 5 | 6 | export default { 7 | console: ConsoleReporter, 8 | perf: PerfReporter, 9 | tap: TapReporter, 10 | html: HtmlReporter 11 | }; 12 | -------------------------------------------------------------------------------- /src/core/version.js: -------------------------------------------------------------------------------- 1 | // Expose the current QUnit version 2 | // Replaced by /rollup.config.js using /build/dist-replace.js 3 | export default '@VERSION'; 4 | -------------------------------------------------------------------------------- /test/benchmark/micro.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Micro benchmark 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/benchmark/micro.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | 3 | require('qunit'); 4 | require('./micro-fixture.js'); 5 | require('./micro-bench.js'); 6 | -------------------------------------------------------------------------------- /test/benchmark/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "qunit": "file:../.." 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/browser-runner/amd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | amd 6 | 7 | 8 | 9 | 10 | 11 |
12 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test/browser-runner/amd.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | 3 | QUnit.module('AMD autostart', { 4 | after: function (assert) { 5 | assert.true(true, 'after hook ran'); 6 | } 7 | }); 8 | 9 | QUnit.test('Prove the test run started as expected', function (assert) { 10 | assert.expect(2); 11 | assert.strictEqual(window.beginData.totalTests, 1, 'Should have expected 1 test'); 12 | }); 13 | -------------------------------------------------------------------------------- /test/browser-runner/autostart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | autostart 6 | 7 | 8 | 9 |
10 | 11 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /test/browser-runner/autostart.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | QUnit.start(); 3 | 4 | QUnit.module('autostart'); 5 | 6 | QUnit.test('Prove the test run started as expected', function (assert) { 7 | var delay = window.times.runStarted - window.times.autostartOff; 8 | assert.pushResult({ 9 | result: delay >= 1000, 10 | actual: delay, 11 | message: 'delay' 12 | }); 13 | assert.strictEqual(window.beginData.totalTests, 1, 'Should have expected 1 test'); 14 | }); 15 | -------------------------------------------------------------------------------- /test/browser-runner/config-fixture-null.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | config-fixture-null 6 | 7 | 8 | 9 | 10 | 11 |
12 |
test markup
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/browser-runner/config-fixture-null.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | QUnit.module('QUnit.config [fixture=null]'); 3 | 4 | QUnit.config.reorder = false; 5 | QUnit.config.fixture = null; 6 | 7 | QUnit.test('make dirty', function (assert) { 8 | assert.strictEqual(QUnit.config.fixture, null); 9 | 10 | var fixture = document.querySelector('#qunit-fixture'); 11 | fixture.textContent = 'dirty'; 12 | }); 13 | 14 | QUnit.test('find dirty', function (assert) { 15 | assert.strictEqual(QUnit.config.fixture, null); 16 | 17 | var fixture = document.querySelector('#qunit-fixture'); 18 | assert.strictEqual(fixture.textContent, 'dirty'); 19 | }); 20 | -------------------------------------------------------------------------------- /test/browser-runner/config-fixture-string.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | config-fixture-string 6 | 7 | 8 | 9 | 10 | 11 |
12 |
test markup
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/browser-runner/config-fixture-string.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | QUnit.module('QUnit.config [fixture=string]'); 3 | 4 | QUnit.config.reorder = false; 5 | QUnit.config.fixture = '

Hi there, stranger!

'; 6 | 7 | QUnit.test('example [first]', function (assert) { 8 | var fixture = document.querySelector('#qunit-fixture'); 9 | 10 | assert.strictEqual(fixture.textContent, 'Hi there, stranger!'); 11 | 12 | fixture.querySelector('strong').remove(); 13 | 14 | assert.strictEqual(fixture.textContent, 'Hi , stranger!'); 15 | }); 16 | 17 | QUnit.test('example [second]', function (assert) { 18 | var fixture = document.querySelector('#qunit-fixture'); 19 | assert.strictEqual(fixture.textContent, 'Hi there, stranger!'); 20 | }); 21 | -------------------------------------------------------------------------------- /test/browser-runner/window-onerror-preexisting-handler.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | window.onerror with pre-existing handler 6 | 7 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /test/browser-runner/window-onerror.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | window-onerror (no pre-existing handler) 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /test/cli/fixtures/.gitignore: -------------------------------------------------------------------------------- 1 | /abcd 2 | /efgh 3 | -------------------------------------------------------------------------------- /test/cli/fixtures/_load-default.tap.txt: -------------------------------------------------------------------------------- 1 | # name: load "test" directory by default 2 | # command: ["qunit"] 3 | 4 | TAP version 13 5 | ok 1 Extension CJS > example 6 | ok 2 Extension MJS > example 7 | ok 3 First > 1 8 | ok 4 Second > 1 9 | 1..4 10 | # pass 4 11 | # skip 0 12 | # todo 0 13 | # fail 0 14 | -------------------------------------------------------------------------------- /test/cli/fixtures/_load-dir-file-glob.tap.txt: -------------------------------------------------------------------------------- 1 | # name: load mixture of file, directory, and glob 2 | # command: ["qunit","test","basic-one.js","glob/**/*-test.js"] 3 | 4 | TAP version 13 5 | ok 1 Single > has a test 6 | ok 2 A-Test > derp 7 | ok 3 Nested-Test > herp 8 | ok 4 Extension CJS > example 9 | ok 5 Extension MJS > example 10 | ok 6 First > 1 11 | ok 7 Second > 1 12 | 1..7 13 | # pass 7 14 | # skip 0 15 | # todo 0 16 | # fail 0 17 | -------------------------------------------------------------------------------- /test/cli/fixtures/_load-dir.tap.txt: -------------------------------------------------------------------------------- 1 | # name: load a directory 2 | # command: ["qunit","test"] 3 | 4 | TAP version 13 5 | ok 1 Extension CJS > example 6 | ok 2 Extension MJS > example 7 | ok 3 First > 1 8 | ok 4 Second > 1 9 | 1..4 10 | # pass 4 11 | # skip 0 12 | # todo 0 13 | # fail 0 -------------------------------------------------------------------------------- /test/cli/fixtures/_load-filenotfound.tap.txt: -------------------------------------------------------------------------------- 1 | # name: load file not found 2 | # command: ["qunit","does-not-exist.js"] 3 | 4 | # stderr 5 | No files were found matching: does-not-exist.js 6 | 7 | # exit code: 1 -------------------------------------------------------------------------------- /test/cli/fixtures/_load-glob.tap.txt: -------------------------------------------------------------------------------- 1 | # name: load glob pattern 2 | # command: ["qunit","glob/**/*-test.js"] 3 | 4 | TAP version 13 5 | ok 1 A-Test > derp 6 | ok 2 Nested-Test > herp 7 | 1..2 8 | # pass 2 9 | # skip 0 10 | # todo 0 11 | # fail 0 -------------------------------------------------------------------------------- /test/cli/fixtures/_load-multiple-files.tap.txt: -------------------------------------------------------------------------------- 1 | # name: load multiple files 2 | # command: ["qunit","basic-one.js","basic-two.js"] 3 | 4 | TAP version 13 5 | ok 1 Single > has a test 6 | ok 2 Double > has a test 7 | ok 3 Double > has another test 8 | 1..3 9 | # pass 3 10 | # skip 0 11 | # todo 0 12 | # fail 0 13 | -------------------------------------------------------------------------------- /test/cli/fixtures/_load-single-file.tap.txt: -------------------------------------------------------------------------------- 1 | # name: load single file 2 | # command: ["qunit","basic-one.js"] 3 | 4 | TAP version 13 5 | ok 1 Single > has a test 6 | 1..1 7 | # pass 1 8 | # skip 0 9 | # todo 0 10 | # fail 0 11 | -------------------------------------------------------------------------------- /test/cli/fixtures/_sourcemap.tap.txt: -------------------------------------------------------------------------------- 1 | # name: normal trace with native source map applied 2 | # command: ["qunit","sourcemap/source.js"] 3 | 4 | TAP version 13 5 | ok 1 Example > good 6 | not ok 2 Example > bad 7 | --- 8 | message: failed 9 | severity: failed 10 | actual : false 11 | expected: true 12 | stack: | 13 | at /qunit/test/cli/fixtures/sourcemap/source.js:7:16 14 | ... 15 | 1..2 16 | # pass 1 17 | # skip 0 18 | # todo 0 19 | # fail 1 20 | 21 | # exit code: 1 -------------------------------------------------------------------------------- /test/cli/fixtures/assert-expect-failure.js: -------------------------------------------------------------------------------- 1 | QUnit.test('failing test', assert => { 2 | assert.expect(2); 3 | assert.true(true); 4 | }); 5 | -------------------------------------------------------------------------------- /test/cli/fixtures/assert-expect-failure.tap.txt: -------------------------------------------------------------------------------- 1 | # name: assert.expect() different count 2 | # command: ["qunit", "assert-expect-failure.js"] 3 | 4 | TAP version 13 5 | not ok 1 failing test 6 | --- 7 | message: Expected 2 assertions, but 1 were run 8 | severity: failed 9 | stack: | 10 | at /qunit/test/cli/fixtures/assert-expect-failure.js:1:7 11 | at internal 12 | ... 13 | 1..1 14 | # pass 0 15 | # skip 0 16 | # todo 0 17 | # fail 1 18 | 19 | # exit code: 1 20 | -------------------------------------------------------------------------------- /test/cli/fixtures/assert-expect-no-assertions.js: -------------------------------------------------------------------------------- 1 | QUnit.test('no assertions', () => { 2 | }); 3 | -------------------------------------------------------------------------------- /test/cli/fixtures/assert-expect-no-assertions.tap.txt: -------------------------------------------------------------------------------- 1 | # name: assert.expect() no assertions 2 | # command: ["qunit", "assert-expect-no-assertions.js"] 3 | 4 | TAP version 13 5 | not ok 1 no assertions 6 | --- 7 | message: Expected at least one assertion, but none were run - call expect(0) to accept zero assertions. 8 | severity: failed 9 | stack: | 10 | at /qunit/test/cli/fixtures/assert-expect-no-assertions.js:1:7 11 | at internal 12 | ... 13 | 1..1 14 | # pass 0 15 | # skip 0 16 | # todo 0 17 | # fail 1 18 | 19 | # exit code: 1 20 | -------------------------------------------------------------------------------- /test/cli/fixtures/assert-failure.js: -------------------------------------------------------------------------------- 1 | // For passing tests, see /test/main/assert.js 2 | // 3 | // TODO: After we migrate running of tests in browsers to use TAP, 4 | // merge these two files and verify them by TAP output instead of 5 | // by boolean passing (akin to what we do with Node.js already). 6 | 7 | QUnit.module('assert', function () { 8 | QUnit.test('true [failure]', function (assert) { 9 | assert.true(false); 10 | }); 11 | 12 | QUnit.test('false [failure]', function (assert) { 13 | assert.false(true); 14 | }); 15 | 16 | QUnit.test('closeTo [failure]', function (assert) { 17 | assert.closeTo(1, 2, 0); 18 | assert.closeTo(1, 2, 1); 19 | assert.closeTo(2, 7, 1); 20 | 21 | assert.closeTo(7, 7.3, 0.1); 22 | assert.closeTo(7, 7.3, 0.2); 23 | assert.closeTo(2011, 2013, 1); 24 | 25 | assert.closeTo(20.7, 20.1, 0.1); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/cli/fixtures/assert-throws-failure.js: -------------------------------------------------------------------------------- 1 | QUnit.module('Throws match', function () { 2 | QUnit.test('bad', function (assert) { 3 | assert.throws(function () { 4 | throw new Error('Match me with a pattern'); 5 | }, /incorrect pattern/, 'match error'); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /test/cli/fixtures/assert-throws-failure.tap.txt: -------------------------------------------------------------------------------- 1 | # name: report assert.throws() failures properly 2 | # command: ["qunit", "assert-throws-failure.js"] 3 | 4 | TAP version 13 5 | not ok 1 Throws match > bad 6 | --- 7 | message: match error 8 | severity: failed 9 | actual : Error: Match me with a pattern 10 | expected: "/incorrect pattern/" 11 | stack: | 12 | at /qunit/test/cli/fixtures/assert-throws-failure.js:3:12 13 | ... 14 | 1..1 15 | # pass 0 16 | # skip 0 17 | # todo 0 18 | # fail 1 19 | 20 | # exit code: 1 21 | -------------------------------------------------------------------------------- /test/cli/fixtures/async-module-error-promise.js: -------------------------------------------------------------------------------- 1 | QUnit.module('module manually returning a promise', function () { 2 | QUnit.test('has a test', function (assert) { 3 | assert.true(true); 4 | }); 5 | return Promise.resolve(1); 6 | }); 7 | -------------------------------------------------------------------------------- /test/cli/fixtures/async-module-error-promise.tap.txt: -------------------------------------------------------------------------------- 1 | # name: module() with promise return value 2 | # command: ["qunit","async-module-error-promise.js"] 3 | 4 | TAP version 13 5 | not ok 1 global failure 6 | --- 7 | message: |+ 8 | Error: Failed to load file async-module-error-promise.js 9 | TypeError: QUnit.module() callback must not be async. For async module setup, use hooks. https://qunitjs.com/api/QUnit/module/#hooks 10 | severity: failed 11 | stack: | 12 | TypeError: QUnit.module() callback must not be async. For async module setup, use hooks. https://qunitjs.com/api/QUnit/module/#hooks 13 | at /qunit/test/cli/fixtures/async-module-error-promise.js:1:7 14 | at internal 15 | ... 16 | Bail out! Error: Failed to load file async-module-error-promise.js 17 | ok 2 module manually returning a promise > has a test 18 | 1..2 19 | # pass 1 20 | # skip 0 21 | # todo 0 22 | # fail 1 23 | 24 | # exit code: 1 25 | -------------------------------------------------------------------------------- /test/cli/fixtures/async-module-error-thenable.js: -------------------------------------------------------------------------------- 1 | QUnit.module('module manually returning a thenable', function () { 2 | QUnit.test('has a test', function (assert) { 3 | assert.true(true); 4 | }); 5 | return { then: function () {} }; 6 | }); 7 | -------------------------------------------------------------------------------- /test/cli/fixtures/async-module-error-thenable.tap.txt: -------------------------------------------------------------------------------- 1 | # name: module() with promise return value 2 | # command: ["qunit","async-module-error-thenable.js"] 3 | 4 | TAP version 13 5 | not ok 1 global failure 6 | --- 7 | message: |+ 8 | Error: Failed to load file async-module-error-thenable.js 9 | TypeError: QUnit.module() callback must not be async. For async module setup, use hooks. https://qunitjs.com/api/QUnit/module/#hooks 10 | severity: failed 11 | stack: | 12 | TypeError: QUnit.module() callback must not be async. For async module setup, use hooks. https://qunitjs.com/api/QUnit/module/#hooks 13 | at /qunit/test/cli/fixtures/async-module-error-thenable.js:1:7 14 | at internal 15 | ... 16 | Bail out! Error: Failed to load file async-module-error-thenable.js 17 | ok 2 module manually returning a thenable > has a test 18 | 1..2 19 | # pass 1 20 | # skip 0 21 | # todo 0 22 | # fail 1 23 | 24 | # exit code: 1 25 | -------------------------------------------------------------------------------- /test/cli/fixtures/async-module-error.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line qunit/no-async-module-callbacks 2 | QUnit.module('module with async callback', async function () { 3 | await Promise.resolve(1); 4 | 5 | QUnit.test('has a test', function (assert) { 6 | assert.true(true); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /test/cli/fixtures/async-module-error.tap.txt: -------------------------------------------------------------------------------- 1 | # name: module() with async function 2 | # command: ["qunit","async-module-error.js"] 3 | 4 | TAP version 13 5 | not ok 1 global failure 6 | --- 7 | message: |+ 8 | Error: Failed to load file async-module-error.js 9 | TypeError: QUnit.module() callback must not be async. For async module setup, use hooks. https://qunitjs.com/api/QUnit/module/#hooks 10 | severity: failed 11 | stack: | 12 | TypeError: QUnit.module() callback must not be async. For async module setup, use hooks. https://qunitjs.com/api/QUnit/module/#hooks 13 | at /qunit/test/cli/fixtures/async-module-error.js:2:7 14 | at internal 15 | ... 16 | Bail out! Error: Failed to load file async-module-error.js 17 | 1..2 18 | # pass 0 19 | # skip 0 20 | # todo 0 21 | # fail 2 22 | 23 | # exit code: 1 24 | -------------------------------------------------------------------------------- /test/cli/fixtures/async-test-throw.js: -------------------------------------------------------------------------------- 1 | QUnit.test('throw early', async function (_assert) { 2 | throw new Error('boo'); 3 | }); 4 | 5 | QUnit.test('throw late', async function (assert) { 6 | await Promise.resolve(''); 7 | assert.true(true); 8 | throw new Error('boo'); 9 | }); 10 | 11 | // See "bad thenable" in /src/test.js#resolvePromise 12 | QUnit.test('test with bad thenable', function (assert) { 13 | assert.true(true); 14 | return { 15 | then: function () { 16 | throw new Error('boo'); 17 | } 18 | }; 19 | }); 20 | -------------------------------------------------------------------------------- /test/cli/fixtures/async-test-throw.tap.txt: -------------------------------------------------------------------------------- 1 | # command: ["qunit", "async-test-throw.js"] 2 | 3 | TAP version 13 4 | not ok 1 throw early 5 | --- 6 | message: "Promise rejected during \"throw early\": boo" 7 | severity: failed 8 | stack: | 9 | Error: boo 10 | at /qunit/test/cli/fixtures/async-test-throw.js:2:9 11 | ... 12 | not ok 2 throw late 13 | --- 14 | message: "Promise rejected during \"throw late\": boo" 15 | severity: failed 16 | stack: | 17 | Error: boo 18 | at /qunit/test/cli/fixtures/async-test-throw.js:8:9 19 | ... 20 | not ok 3 test with bad thenable 21 | --- 22 | message: "Promise rejected during \"test with bad thenable\": boo" 23 | severity: failed 24 | stack: | 25 | Error: boo 26 | at /qunit/test/cli/fixtures/async-test-throw.js:16:13 27 | ... 28 | 1..3 29 | # pass 0 30 | # skip 0 31 | # todo 0 32 | # fail 3 33 | 34 | # exit code: 1 35 | -------------------------------------------------------------------------------- /test/cli/fixtures/basic-fail.js: -------------------------------------------------------------------------------- 1 | QUnit.test('foo', function (assert) { 2 | assert.true(true); 3 | }); 4 | QUnit.test('bar', function (assert) { 5 | assert.true(false); 6 | }); 7 | QUnit.test('baz', function (assert) { 8 | assert.true(true); 9 | }); 10 | -------------------------------------------------------------------------------- /test/cli/fixtures/basic-one.js: -------------------------------------------------------------------------------- 1 | QUnit.module('Single', function () { 2 | QUnit.test('has a test', function (assert) { 3 | assert.true(true); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /test/cli/fixtures/basic-two.js: -------------------------------------------------------------------------------- 1 | QUnit.module('Double', function () { 2 | QUnit.test('has a test', function (assert) { 3 | assert.true(true); 4 | }); 5 | 6 | QUnit.test('has another test', function (assert) { 7 | assert.true(true); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/cli/fixtures/callbacks-promises.tap.txt: -------------------------------------------------------------------------------- 1 | # command: ["qunit", "callbacks-promises.js"] 2 | 3 | TAP version 13 4 | ok 1 module1 > nestedModule1 > test1 5 | ok 2 module1 > test2 6 | ok 3 module1 > nestedModule2 > test3 7 | 1..3 8 | # pass 3 9 | # skip 0 10 | # todo 0 11 | # fail 0 12 | 13 | # stderr 14 | CALLBACK: begin 15 | CALLBACK: begin2 16 | CALLBACK: moduleStart 17 | CALLBACK: moduleStart 18 | CALLBACK: testStart - test1 19 | CALLBACK: testDone - test1 20 | CALLBACK: moduleDone - module1 > nestedModule1 21 | CALLBACK: testStart - test2 22 | CALLBACK: testDone - test2 23 | CALLBACK: moduleStart 24 | CALLBACK: testStart - test3 25 | CALLBACK: testDone - test3 26 | CALLBACK: moduleDone - module1 > nestedModule2 27 | CALLBACK: moduleDone - module1 28 | CALLBACK: done 29 | -------------------------------------------------------------------------------- /test/cli/fixtures/callbacks-rejected.js: -------------------------------------------------------------------------------- 1 | let caught = []; 2 | 3 | QUnit.on('error', function (e) { 4 | caught.push(e.message); 5 | }); 6 | 7 | QUnit.begin(function () { 8 | return Promise.reject(new Error('begin')); 9 | }); 10 | 11 | QUnit.moduleStart(function () { 12 | return Promise.reject(new Error('moduleStart')); 13 | }); 14 | 15 | QUnit.testStart(function () { 16 | return Promise.reject(new Error('testStart')); 17 | }); 18 | 19 | QUnit.done(function () { 20 | setTimeout(function () { 21 | console.log('Caught errors from ' + caught.join(', ')); 22 | }, 100); 23 | }); 24 | 25 | QUnit.done(function () { 26 | return Promise.reject(new Error('done')); 27 | }); 28 | 29 | QUnit.test('one', function (assert) { 30 | assert.ok(true); 31 | }); 32 | 33 | QUnit.module('example', function () { 34 | QUnit.test('two', function (assert) { 35 | assert.ok(true); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/cli/fixtures/callbacks-rejected.tap.txt: -------------------------------------------------------------------------------- 1 | # name: rejection from callbacks 2 | # command: ["qunit", "callbacks-rejected.js"] 3 | 4 | TAP version 13 5 | not ok 1 global failure 6 | --- 7 | message: Error: begin 8 | severity: failed 9 | stack: | 10 | Error: begin 11 | at /qunit/test/cli/fixtures/callbacks-rejected.js:8:25 12 | at qunit.js 13 | at internal 14 | ... 15 | Bail out! Error: begin 16 | 17 | # stderr 18 | Error: Process exited before tests finished running 19 | 20 | # exit code: 1 21 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-filter-regex-exclude.js: -------------------------------------------------------------------------------- 1 | // regular expression (case-sensitive), inverted 2 | QUnit.config.filter = '!/Foo|bar/'; 3 | 4 | QUnit.module('filter'); 5 | 6 | QUnit.test('foo test', function (assert) { 7 | assert.true(true); 8 | }); 9 | 10 | QUnit.test('Foo test', function (assert) { 11 | assert.true(false, 'Foo is excluded'); 12 | }); 13 | 14 | QUnit.test('bar test', function (assert) { 15 | assert.true(false, 'bar is excluded'); 16 | }); 17 | 18 | QUnit.test('Bar test', function (assert) { 19 | assert.true(true); 20 | }); 21 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-filter-regex-exclude.tap.txt: -------------------------------------------------------------------------------- 1 | # name: config.filter with inverted regex 2 | # command: ["qunit","config-filter-regex-exclude.js"] 3 | 4 | TAP version 13 5 | ok 1 filter > foo test 6 | ok 2 filter > Bar test 7 | 1..2 8 | # pass 2 9 | # skip 0 10 | # todo 0 11 | # fail 0 -------------------------------------------------------------------------------- /test/cli/fixtures/config-filter-regex.js: -------------------------------------------------------------------------------- 1 | // regular expression (case-insensitive) 2 | QUnit.config.filter = '/foo|bar/i'; 3 | 4 | QUnit.module('filter'); 5 | 6 | QUnit.test('foo test', function (assert) { 7 | assert.true(true); 8 | }); 9 | 10 | QUnit.test('FOO test', function (assert) { 11 | assert.true(true); 12 | }); 13 | 14 | QUnit.test('boo test', function (assert) { 15 | assert.true(false, 'boo does not match'); 16 | }); 17 | 18 | QUnit.test('bar test', function (assert) { 19 | assert.true(true); 20 | }); 21 | 22 | QUnit.test('baz test', function (assert) { 23 | assert.true(false, 'baz does not match'); 24 | }); 25 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-filter-regex.tap.txt: -------------------------------------------------------------------------------- 1 | # name: config.filter with a regex 2 | # command: ["qunit","config-filter-regex.js"] 3 | 4 | TAP version 13 5 | ok 1 filter > foo test 6 | ok 2 filter > FOO test 7 | ok 3 filter > bar test 8 | 1..3 9 | # pass 3 10 | # skip 0 11 | # todo 0 12 | # fail 0 -------------------------------------------------------------------------------- /test/cli/fixtures/config-filter-string.js: -------------------------------------------------------------------------------- 1 | // case-insensitive string that looks like a regex but isn't, inverted 2 | QUnit.config.filter = '!foo|bar'; 3 | 4 | QUnit.module('filter'); 5 | 6 | QUnit.test('foo test', function (assert) { 7 | assert.true(true); 8 | }); 9 | 10 | QUnit.test('bar test', function (assert) { 11 | assert.true(true); 12 | }); 13 | 14 | QUnit.test('foo|bar test', function (assert) { 15 | assert.true(false, "'foo|bar' is excluded"); 16 | }); 17 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-filter-string.tap.txt: -------------------------------------------------------------------------------- 1 | # name: config.filter with a string 2 | # command: ["qunit","config-filter-string.js"] 3 | 4 | TAP version 13 5 | ok 1 filter > foo test 6 | ok 2 filter > bar test 7 | 1..2 8 | # pass 2 9 | # skip 0 10 | # todo 0 11 | # fail 0 -------------------------------------------------------------------------------- /test/cli/fixtures/config-module.js: -------------------------------------------------------------------------------- 1 | QUnit.config.module = 'MODULE b'; 2 | 3 | QUnit.module('Module A', () => { 4 | QUnit.test('Test A', assert => { 5 | assert.true(false); 6 | }); 7 | }); 8 | 9 | QUnit.module('Module B', () => { 10 | QUnit.test('Test B', assert => { 11 | assert.true(true); 12 | }); 13 | }); 14 | 15 | QUnit.module('Module C', () => { 16 | QUnit.test('Test C', assert => { 17 | assert.true(false); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-module.tap.txt: -------------------------------------------------------------------------------- 1 | # name: config.module 2 | # command: ["qunit","config-module.js"] 3 | 4 | TAP version 13 5 | ok 1 Module B > Test B 6 | 1..1 7 | # pass 1 8 | # skip 0 9 | # todo 0 10 | # fail 0 -------------------------------------------------------------------------------- /test/cli/fixtures/config-moduleId.tap.txt: -------------------------------------------------------------------------------- 1 | # name: config.moduleId 2 | # command: ["qunit", "config-moduleId.js"] 3 | 4 | TAP version 13 5 | ok 1 module A scoped > module C nested > test C1 6 | ok 2 module D scoped > test D1 7 | ok 3 module D scoped > module E nested > test E1 8 | ok 4 module D scoped > test D2 9 | ok 5 module F flat > test F1 10 | 1..5 11 | # pass 5 12 | # skip 0 13 | # todo 0 14 | # fail 0 15 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-noglobals-add.js: -------------------------------------------------------------------------------- 1 | QUnit.config.noglobals = true; 2 | 3 | QUnit.test('adds global var', assert => { 4 | global.dummyGlobal = 'hello'; 5 | assert.true(true); 6 | }); 7 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-noglobals-add.tap.txt: -------------------------------------------------------------------------------- 1 | # name: config.noglobals and add a global 2 | # command: ["qunit", "config-noglobals-add.js"] 3 | 4 | TAP version 13 5 | not ok 1 adds global var 6 | --- 7 | message: Introduced global variable(s): dummyGlobal 8 | severity: failed 9 | ... 10 | 1..1 11 | # pass 0 12 | # skip 0 13 | # todo 0 14 | # fail 1 15 | 16 | # exit code: 1 17 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-noglobals-ignored.js: -------------------------------------------------------------------------------- 1 | QUnit.config.noglobals = true; 2 | 3 | QUnit.test('adds global var', assert => { 4 | global['qunit-test-output-dummy'] = 'hello'; 5 | assert.true(true); 6 | }); 7 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-noglobals-ignored.tap.txt: -------------------------------------------------------------------------------- 1 | # name: config.noglobals and add ignored DOM global 2 | # command: ["qunit", "config-noglobals-ignored.js"] 3 | 4 | TAP version 13 5 | ok 1 adds global var 6 | 1..1 7 | # pass 1 8 | # skip 0 9 | # todo 0 10 | # fail 0 11 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-noglobals-remove.js: -------------------------------------------------------------------------------- 1 | QUnit.config.noglobals = true; 2 | 3 | global.dummyGlobal = 'hello'; 4 | 5 | QUnit.test('deletes global var', assert => { 6 | delete global.dummyGlobal; 7 | assert.true(true); 8 | }); 9 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-noglobals-remove.tap.txt: -------------------------------------------------------------------------------- 1 | # name: config.noglobals and remove a global 2 | # command: ["qunit","config-noglobals-remove.js"] 3 | 4 | TAP version 13 5 | not ok 1 deletes global var 6 | --- 7 | message: Deleted global variable(s): dummyGlobal 8 | severity: failed 9 | ... 10 | 1..1 11 | # pass 0 12 | # skip 0 13 | # todo 0 14 | # fail 1 15 | 16 | # exit code: 1 17 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-notrycatch-hook-rejection.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | process.on('unhandledRejection', (reason) => { 4 | console.log('FOUND Unhandled Rejection:', reason); 5 | }); 6 | 7 | QUnit.config.testTimeout = 1000; 8 | QUnit.config.notrycatch = true; 9 | 10 | QUnit.module('example', function (hooks) { 11 | hooks.beforeEach(() => { 12 | return Promise.reject('bad things happen'); 13 | }); 14 | 15 | QUnit.test('passing test', assert => { 16 | assert.true(true); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-notrycatch-hook-rejection.tap.txt: -------------------------------------------------------------------------------- 1 | # command: ["qunit", "config-notrycatch-hook-rejection.js"] 2 | 3 | TAP version 13 4 | FOUND Unhandled Rejection: bad things happen 5 | not ok 1 example > passing test 6 | --- 7 | message: global failure: bad things happen 8 | severity: failed 9 | stack: | 10 | at internal 11 | ... 12 | --- 13 | message: Test took longer than 1000ms; test timed out. 14 | severity: failed 15 | ... 16 | 1..1 17 | # pass 0 18 | # skip 0 19 | # todo 0 20 | # fail 1 21 | 22 | # exit code: 1 23 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-notrycatch-test-rejection.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | process.on('unhandledRejection', (reason) => { 4 | console.log('FOUND Unhandled Rejection:', reason); 5 | }); 6 | 7 | QUnit.config.testTimeout = 1000; 8 | QUnit.config.notrycatch = true; 9 | 10 | QUnit.module('example', function () { 11 | QUnit.test('returns a rejected promise', function () { 12 | return Promise.reject('bad things happen'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-notrycatch-test-rejection.tap.txt: -------------------------------------------------------------------------------- 1 | # command: ["qunit", "config-notrycatch-test-rejection.js"] 2 | 3 | TAP version 13 4 | FOUND Unhandled Rejection: bad things happen 5 | not ok 1 example > returns a rejected promise 6 | --- 7 | message: global failure: bad things happen 8 | severity: failed 9 | stack: | 10 | at internal 11 | ... 12 | --- 13 | message: Test took longer than 1000ms; test timed out. 14 | severity: failed 15 | ... 16 | 1..1 17 | # pass 0 18 | # skip 0 19 | # todo 0 20 | # fail 1 21 | 22 | # exit code: 1 23 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-requireExpects.js: -------------------------------------------------------------------------------- 1 | QUnit.config.requireExpects = true; 2 | 3 | QUnit.test('passing test', assert => { 4 | assert.true(true); 5 | }); 6 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-requireExpects.tap.txt: -------------------------------------------------------------------------------- 1 | # name: assert.expect() missing and config.requireExpects=true 2 | # command: ["qunit","config-requireExpects.js"] 3 | 4 | TAP version 13 5 | not ok 1 passing test 6 | --- 7 | message: Expected number of assertions to be defined, but expect() was not called. 8 | severity: failed 9 | stack: | 10 | at /qunit/test/cli/fixtures/config-requireExpects.js:3:7 11 | at internal 12 | ... 13 | 1..1 14 | # pass 0 15 | # skip 0 16 | # todo 0 17 | # fail 1 18 | 19 | # exit code: 1 20 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-testId.tap.txt: -------------------------------------------------------------------------------- 1 | # name: config.testId 2 | # command: ["qunit","config-testId.js"] 3 | 4 | TAP version 13 5 | ok 1 test 2 6 | ok 2 module A > module B > test 1 7 | ok 3 module A > module C > test 2 8 | ok 4 module D > test 1 9 | 1..4 10 | # pass 4 11 | # skip 0 12 | # todo 0 13 | # fail 0 -------------------------------------------------------------------------------- /test/cli/fixtures/config-testTimeout-invalid.js: -------------------------------------------------------------------------------- 1 | QUnit.test('invalid [undefined]', function (assert) { 2 | QUnit.config.testTimeout = undefined; 3 | setTimeout(assert.async(), 7); 4 | assert.true(true); 5 | }); 6 | 7 | QUnit.test('invalid [null]', function (assert) { 8 | QUnit.config.testTimeout = null; 9 | setTimeout(assert.async(), 7); 10 | assert.true(true); 11 | }); 12 | 13 | QUnit.test('invalid [string]', function (assert) { 14 | QUnit.config.testTimeout = '9412'; 15 | setTimeout(assert.async(), 7); 16 | assert.true(true); 17 | }); 18 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-testTimeout-invalid.tap.txt: -------------------------------------------------------------------------------- 1 | # command: ["qunit", "config-testTimeout-invalid.js"] 2 | 3 | TAP version 13 4 | ok 1 invalid [undefined] 5 | ok 2 invalid [null] 6 | ok 3 invalid [string] 7 | 1..3 8 | # pass 3 9 | # skip 0 10 | # todo 0 11 | # fail 0 12 | 13 | # stderr 14 | QUnit.config.testTimeout was set to an an invalid value (undefined). Using default. https://qunitjs.com/api/config/testTimeout/ 15 | QUnit.config.testTimeout was set to an an invalid value (null). Using default. https://qunitjs.com/api/config/testTimeout/ 16 | QUnit.config.testTimeout was set to an an invalid value (string). Using default. https://qunitjs.com/api/config/testTimeout/ 17 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-testTimeout.js: -------------------------------------------------------------------------------- 1 | process.on('unhandledRejection', (reason) => { 2 | console.log('Unhandled Rejection:', reason); 3 | }); 4 | 5 | QUnit.config.testTimeout = 10; 6 | 7 | QUnit.test('slow', () => { 8 | return new Promise(resolve => setTimeout(resolve, 20)); 9 | }); 10 | -------------------------------------------------------------------------------- /test/cli/fixtures/config-testTimeout.tap.txt: -------------------------------------------------------------------------------- 1 | # name: config.testTimeout 2 | # command: ["qunit", "config-testTimeout.js"] 3 | 4 | TAP version 13 5 | not ok 1 slow 6 | --- 7 | message: Test took longer than 10ms; test timed out. 8 | severity: failed 9 | ... 10 | 1..1 11 | # pass 0 12 | # skip 0 13 | # todo 0 14 | # fail 1 15 | 16 | # exit code: 1 17 | -------------------------------------------------------------------------------- /test/cli/fixtures/done-after-timeout.js: -------------------------------------------------------------------------------- 1 | QUnit.test('times out before scheduled done is called', assert => { 2 | assert.timeout(10); 3 | const done = assert.async(); 4 | assert.true(true); 5 | setTimeout(done, 100); 6 | }); 7 | -------------------------------------------------------------------------------- /test/cli/fixtures/done-after-timeout.tap.txt: -------------------------------------------------------------------------------- 1 | # name: assert.async() handled after timeout 2 | # command: ["qunit","done-after-timeout.js"] 3 | 4 | TAP version 13 5 | not ok 1 times out before scheduled done is called 6 | --- 7 | message: Test took longer than 10ms; test timed out. 8 | severity: failed 9 | ... 10 | 1..1 11 | # pass 0 12 | # skip 0 13 | # todo 0 14 | # fail 1 15 | 16 | # exit code: 1 17 | -------------------------------------------------------------------------------- /test/cli/fixtures/drooling-done.js: -------------------------------------------------------------------------------- 1 | QUnit.config.reorder = false; 2 | 3 | let done; 4 | 5 | QUnit.test('Test A', assert => { 6 | assert.ok(true); 7 | done = assert.async(); 8 | throw new Error('this is an intentional error'); 9 | }); 10 | 11 | QUnit.test('Test B', assert => { 12 | assert.ok(true); 13 | 14 | // This bad call is silently ignored because "Test A" already failed 15 | // and we cancelled the async pauses. 16 | done(); 17 | }); 18 | -------------------------------------------------------------------------------- /test/cli/fixtures/drooling-done.tap.txt: -------------------------------------------------------------------------------- 1 | # name: assert.async() handled after fail in other test 2 | # command: ["qunit", "drooling-done.js"] 3 | 4 | TAP version 13 5 | not ok 1 Test A 6 | --- 7 | message: |+ 8 | Died on test #2: this is an intentional error 9 | at /qunit/test/cli/fixtures/drooling-done.js:5:7 10 | at internal 11 | severity: failed 12 | stack: | 13 | Error: this is an intentional error 14 | at /qunit/test/cli/fixtures/drooling-done.js:8:9 15 | ... 16 | ok 2 Test B 17 | 1..2 18 | # pass 1 19 | # skip 0 20 | # todo 0 21 | # fail 1 22 | 23 | # exit code: 1 24 | 25 | -------------------------------------------------------------------------------- /test/cli/fixtures/drooling-extra-done-outside.js: -------------------------------------------------------------------------------- 1 | QUnit.test('extra done scheduled outside any test', assert => { 2 | assert.timeout(10); 3 | const done = assert.async(); 4 | assert.true(true); 5 | 6 | // Later, boom! 7 | setTimeout(done, 100); 8 | 9 | // Passing, end of test 10 | done(); 11 | }); 12 | -------------------------------------------------------------------------------- /test/cli/fixtures/drooling-extra-done-outside.tap.txt: -------------------------------------------------------------------------------- 1 | # name: assert.async() handled outside test 2 | # command: ["qunit","drooling-extra-done-outside.js"] 3 | 4 | TAP version 13 5 | ok 1 extra done scheduled outside any test 6 | 1..1 7 | # pass 1 8 | # skip 0 9 | # todo 0 10 | # fail 0 11 | Bail out! Error: Unexpected release of async pause after tests finished. 12 | --- 13 | message: |+ 14 | Error: Unexpected release of async pause after tests finished. 15 | > Test: extra done scheduled outside any test [async #1] 16 | severity: failed 17 | stack: | 18 | Error: Unexpected release of async pause after tests finished. 19 | > Test: extra done scheduled outside any test [async #1] 20 | at qunit.js 21 | at internal 22 | ... 23 | 24 | # exit code: 1 -------------------------------------------------------------------------------- /test/cli/fixtures/drooling-extra-done.js: -------------------------------------------------------------------------------- 1 | QUnit.config.reorder = false; 2 | 3 | let done; 4 | 5 | QUnit.test('Test A', assert => { 6 | assert.ok(true); 7 | done = assert.async(); 8 | 9 | // Passing. 10 | done(); 11 | }); 12 | 13 | QUnit.test('Test B', assert => { 14 | assert.ok(true); 15 | 16 | // Boom 17 | done(); 18 | }); 19 | -------------------------------------------------------------------------------- /test/cli/fixtures/drooling-extra-done.tap.txt: -------------------------------------------------------------------------------- 1 | # name: assert.async() handled again in other test 2 | # command: ["qunit", "drooling-extra-done.js"] 3 | 4 | TAP version 13 5 | ok 1 Test A 6 | not ok 2 Test B 7 | --- 8 | message: |+ 9 | Died on test #2: Unexpected release of async pause during a different test. 10 | > Test: Test A [async #1] 11 | at /qunit/test/cli/fixtures/drooling-extra-done.js:13:7 12 | at internal 13 | severity: failed 14 | stack: | 15 | Error: Unexpected release of async pause during a different test. 16 | > Test: Test A [async #1] 17 | ... 18 | 1..2 19 | # pass 1 20 | # skip 0 21 | # todo 0 22 | # fail 1 23 | 24 | # exit code: 1 25 | -------------------------------------------------------------------------------- /test/cli/fixtures/each-array-labels.js: -------------------------------------------------------------------------------- 1 | // Automatic labels for test.each() array data where possible 2 | // https://github.com/qunitjs/qunit/issues/1733 3 | 4 | QUnit.test.each('array of arrays', [[1, 2, 3], [1, 1, 2]], function (assert, _data) { 5 | assert.true(true); 6 | }); 7 | 8 | QUnit.test.each('array of simple strings', [ 9 | 'foo', 10 | 'x'.repeat(40), 11 | '$', 12 | 'http://example.org', 13 | ' ', 14 | '' 15 | ], function (assert, _data) { 16 | assert.true(true); 17 | }); 18 | 19 | QUnit.test.each('array of mixed', [ 20 | undefined, 21 | null, 22 | false, 23 | true, 24 | 0, 25 | 1, 26 | -10, 27 | 10 / 3, 28 | 10e42, 29 | Infinity, 30 | NaN, 31 | [], 32 | {}, 33 | '999: example', 34 | 'simple string', 35 | '\b', 36 | '\n', 37 | 'y'.repeat(100) 38 | ], function (assert, _value) { 39 | assert.true(true); 40 | }); 41 | 42 | QUnit.test.each('keyed objects', { caseFoo: [1, 2, 3], caseBar: [1, 1, 2] }, function (assert, _data) { 43 | assert.true(true); 44 | }); 45 | -------------------------------------------------------------------------------- /test/cli/fixtures/event-runEnd-memory.js: -------------------------------------------------------------------------------- 1 | QUnit.on('runEnd', function (run) { 2 | console.log(`# early runEnd total=${run.testCounts.total} passed=${run.testCounts.passed} failed=${run.testCounts.failed}`); 3 | setTimeout(function () { 4 | QUnit.on('runEnd', function (run) { 5 | console.log(`# late runEnd total=${run.testCounts.total} passed=${run.testCounts.passed} failed=${run.testCounts.failed}`); 6 | }); 7 | }); 8 | }); 9 | 10 | QUnit.module('First', function () { 11 | QUnit.test('A', function (assert) { 12 | assert.true(true); 13 | }); 14 | QUnit.test('B', function (assert) { 15 | assert.true(false); 16 | }); 17 | }); 18 | 19 | QUnit.module('Second', function () { 20 | QUnit.test('C', function (assert) { 21 | assert.true(true); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/cli/fixtures/event-runEnd-memory.tap.txt: -------------------------------------------------------------------------------- 1 | # command: ["qunit", "event-runEnd-memory.js"] 2 | 3 | TAP version 13 4 | ok 1 First > A 5 | not ok 2 First > B 6 | --- 7 | message: failed 8 | severity: failed 9 | actual : false 10 | expected: true 11 | stack: | 12 | at /qunit/test/cli/fixtures/event-runEnd-memory.js:15:16 13 | ... 14 | ok 3 Second > C 15 | 1..3 16 | # pass 2 17 | # skip 0 18 | # todo 0 19 | # fail 1 20 | # early runEnd total=3 passed=2 failed=1 21 | # late runEnd total=3 passed=2 failed=1 22 | 23 | # exit code: 1 24 | -------------------------------------------------------------------------------- /test/cli/fixtures/filter-modulename-insensitive.tap.txt: -------------------------------------------------------------------------------- 1 | # name: --module selects a module (case-insensitive) 2 | # command: ["qunit", "--module", "seconD", "test/"] 3 | 4 | TAP version 13 5 | ok 1 Second > 1 6 | 1..1 7 | # pass 1 8 | # skip 0 9 | # todo 0 10 | # fail 0 11 | -------------------------------------------------------------------------------- /test/cli/fixtures/filter-modulename.tap.txt: -------------------------------------------------------------------------------- 1 | # name: --filter matches module 2 | # command: ["qunit", "--filter", "single", "test", "basic-one.js", "glob/**/*-test.js"] 3 | 4 | TAP version 13 5 | ok 1 Single > has a test 6 | 1..1 7 | # pass 1 8 | # skip 0 9 | # todo 0 10 | # fail 0 11 | -------------------------------------------------------------------------------- /test/cli/fixtures/glob/a-test.js: -------------------------------------------------------------------------------- 1 | QUnit.module('A-Test', function () { 2 | QUnit.test('derp', function (assert) { 3 | assert.true(true); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /test/cli/fixtures/glob/not-a.js: -------------------------------------------------------------------------------- 1 | QUnit.module('Not-A', function () { 2 | QUnit.test('1', function (assert) { 3 | assert.true(true); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /test/cli/fixtures/glob/sub/nested-test.js: -------------------------------------------------------------------------------- 1 | QUnit.module('Nested-Test', function () { 2 | QUnit.test('herp', function (assert) { 3 | assert.true(true); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /test/cli/fixtures/hanging-test.js: -------------------------------------------------------------------------------- 1 | QUnit.test('hanging', function (assert) { 2 | assert.async(); 3 | }); 4 | -------------------------------------------------------------------------------- /test/cli/fixtures/hanging-test.tap.txt: -------------------------------------------------------------------------------- 1 | # name: test that hangs 2 | # command: ["qunit", "hanging-test.js"] 3 | 4 | TAP version 13 5 | not ok 1 hanging 6 | --- 7 | message: Test took longer than 3000ms; test timed out. 8 | severity: failed 9 | ... 10 | 1..1 11 | # pass 0 12 | # skip 0 13 | # todo 0 14 | # fail 1 15 | 16 | # exit code: 1 17 | -------------------------------------------------------------------------------- /test/cli/fixtures/hooks-global-context.tap.txt: -------------------------------------------------------------------------------- 1 | # name: QUnit.hooks context 2 | # command: ["qunit", "hooks-global-context.js"] 3 | 4 | TAP version 13 5 | ok 1 A > A1 6 | ok 2 A > AB > AB1 7 | ok 3 B 8 | 1..3 9 | # pass 3 10 | # skip 0 11 | # todo 0 12 | # fail 0 13 | -------------------------------------------------------------------------------- /test/cli/fixtures/inception.js: -------------------------------------------------------------------------------- 1 | const outerQUnit = globalThis.QUnit; 2 | delete globalThis.QUnit; 3 | const myQUnit = require('../../../src/cli/require-qunit')(); 4 | globalThis.QUnit = outerQUnit; 5 | 6 | const data = []; 7 | myQUnit.on('runStart', function () { 8 | data.push('runStart'); 9 | }); 10 | myQUnit.on('testEnd', function () { 11 | data.push('testEnd'); 12 | }); 13 | myQUnit.on('runEnd', function () { 14 | data.push('runEnd'); 15 | }); 16 | 17 | myQUnit.module('example', function () { 18 | myQUnit.test('a', function (assert) { 19 | assert.true(true, 'message'); 20 | }); 21 | }); 22 | 23 | const myQunitRun = new Promise(resolve => { 24 | myQUnit.on('runEnd', resolve); 25 | }); 26 | 27 | myQUnit.start(); 28 | 29 | QUnit.test('inception', async function (assert) { 30 | await myQunitRun; 31 | 32 | assert.deepEqual(data, [ 33 | 'runStart', 34 | 'testEnd', 35 | 'runEnd' 36 | ]); 37 | }); 38 | -------------------------------------------------------------------------------- /test/cli/fixtures/inception.tap.txt: -------------------------------------------------------------------------------- 1 | # command: ["qunit", "inception.js"] 2 | 3 | TAP version 13 4 | ok 1 inception 5 | 1..1 6 | # pass 1 7 | # skip 0 8 | # todo 0 9 | # fail 0 10 | -------------------------------------------------------------------------------- /test/cli/fixtures/memory-leak-module-closure-filtered.tap.txt: -------------------------------------------------------------------------------- 1 | # name: memory leak module-closure filtered 2 | # command: ["node", "--expose-gc", "../../../bin/qunit.js", "--filter", "!child", "memory-leak-module-closure.js"] 3 | 4 | TAP version 13 5 | ok 1 module-closure > example test 6 | ok 2 module-closure check > memory release 7 | 1..2 8 | # pass 2 9 | # skip 0 10 | # todo 0 11 | # fail 0 12 | -------------------------------------------------------------------------------- /test/cli/fixtures/memory-leak-module-closure-unfiltered.tap.txt: -------------------------------------------------------------------------------- 1 | # name: memory leak module-closure unfiltered 2 | # command: ["node", "--expose-gc", "../../../bin/qunit.js", "memory-leak-module-closure.js"] 3 | 4 | TAP version 13 5 | ok 1 module-closure > example test 6 | ok 2 module-closure > example child module > example child module test 7 | ok 3 module-closure check > memory release 8 | 1..3 9 | # pass 3 10 | # skip 0 11 | # todo 0 12 | # fail 0 -------------------------------------------------------------------------------- /test/cli/fixtures/memory-leak-test-object.tap.txt: -------------------------------------------------------------------------------- 1 | # name: memory leak test-object 2 | # command: ["node", "--expose-gc", "../../../bin/qunit.js", "memory-leak-test-object.js"] 3 | 4 | TAP version 13 5 | ok 1 test-object > example test 6 | 1..1 7 | # pass 1 8 | # skip 0 9 | # todo 0 10 | # fail 0 11 | -------------------------------------------------------------------------------- /test/cli/fixtures/module-nested.js: -------------------------------------------------------------------------------- 1 | // Regression test for https://github.com/qunitjs/qunit/issues/1478 2 | 3 | try { 4 | QUnit.module('module 1', () => { 5 | QUnit.test('test in module 1', assert => { 6 | assert.true(true); 7 | }); 8 | }); 9 | } catch (e) { 10 | // Ignore 11 | } 12 | 13 | try { 14 | QUnit.module('module 2', () => { 15 | // trigger an error in executeNow 16 | undefined(); 17 | 18 | QUnit.test('test in module 2', assert => { 19 | assert.true(true); 20 | }); 21 | }); 22 | } catch (e) { 23 | // Ignore 24 | } 25 | 26 | try { 27 | QUnit.module('module 3', () => { 28 | QUnit.test('test in module 3', assert => { 29 | assert.true(true); 30 | }); 31 | }); 32 | } catch (e) { 33 | // Ignore 34 | } 35 | -------------------------------------------------------------------------------- /test/cli/fixtures/module-nested.tap.txt: -------------------------------------------------------------------------------- 1 | # name: module() nested with interrupted executeNow 2 | # command: ["qunit", "module-nested.js"] 3 | 4 | TAP version 13 5 | ok 1 module 1 > test in module 1 6 | ok 2 module 3 > test in module 3 7 | 1..2 8 | # pass 2 9 | # skip 0 10 | # todo 0 11 | # fail 0 12 | -------------------------------------------------------------------------------- /test/cli/fixtures/no-tests-failOnZeroTests.js: -------------------------------------------------------------------------------- 1 | // no tests 2 | QUnit.config.failOnZeroTests = false; 3 | -------------------------------------------------------------------------------- /test/cli/fixtures/no-tests-failOnZeroTests.tap.txt: -------------------------------------------------------------------------------- 1 | # name: no tests and config.failOnZeroTests=false 2 | # command: ["qunit", "no-tests-failOnZeroTests.js"] 3 | 4 | TAP version 13 5 | 1..0 6 | # pass 0 7 | # skip 0 8 | # todo 0 9 | # fail 0 10 | -------------------------------------------------------------------------------- /test/cli/fixtures/no-tests.js: -------------------------------------------------------------------------------- 1 | // This test file has no tests! 2 | -------------------------------------------------------------------------------- /test/cli/fixtures/no-tests.tap.txt: -------------------------------------------------------------------------------- 1 | # name: no tests 2 | # command: ["qunit", "no-tests.js"] 3 | 4 | TAP version 13 5 | not ok 1 global failure 6 | --- 7 | message: Error: No tests were run. 8 | severity: failed 9 | stack: | 10 | Error: No tests were run. 11 | ... 12 | Bail out! Error: No tests were run. 13 | 1..1 14 | # pass 0 15 | # skip 0 16 | # todo 0 17 | # fail 1 18 | 19 | # exit code: 1 20 | -------------------------------------------------------------------------------- /test/cli/fixtures/node_modules/require-dep/index.js: -------------------------------------------------------------------------------- 1 | console.log( "required require-dep/index.js" ); 2 | -------------------------------------------------------------------------------- /test/cli/fixtures/node_modules/require-dep/module.js: -------------------------------------------------------------------------------- 1 | console.log( "required require-dep/module.js" ); 2 | -------------------------------------------------------------------------------- /test/cli/fixtures/node_modules/require-dep/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "name": "require-dep" 4 | } 5 | -------------------------------------------------------------------------------- /test/cli/fixtures/npm-reporter/index.js: -------------------------------------------------------------------------------- 1 | function NPMReporter (runner) { 2 | runner.on('runEnd', this.onRunEnd); 3 | } 4 | 5 | NPMReporter.init = function (runner) { 6 | return new NPMReporter(runner); 7 | }; 8 | 9 | NPMReporter.prototype.onRunEnd = function () { 10 | console.log('Run ended!'); 11 | }; 12 | 13 | module.exports = NPMReporter; 14 | -------------------------------------------------------------------------------- /test/cli/fixtures/npm-reporter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "name": "npm-reporter", 4 | "private": true, 5 | "keywords": [ 6 | "qunit-plugin", 7 | "js-reporter" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /test/cli/fixtures/only-module-flat.js: -------------------------------------------------------------------------------- 1 | QUnit.module('module A'); 2 | QUnit.test('test A', function (assert) { 3 | assert.true(false, 'this test should not run'); 4 | }); 5 | 6 | QUnit.module.only('module B'); 7 | QUnit.todo('test B', function (assert) { 8 | assert.true(false, 'not implemented yet'); 9 | }); 10 | QUnit.skip('test C', function (assert) { 11 | assert.true(false, 'test should be skipped'); 12 | }); 13 | QUnit.test('test D', function (assert) { 14 | assert.true(true, 'this test should run'); 15 | }); 16 | 17 | QUnit.module('module C'); 18 | QUnit.todo('test E', function (assert) { 19 | assert.true(false, 'not implemented yet'); 20 | }); 21 | QUnit.skip('test F', function (assert) { 22 | assert.true(false, 'test should be skipped'); 23 | }); 24 | QUnit.test('test G', function (assert) { 25 | assert.true(false, 'this test should not run'); 26 | }); 27 | -------------------------------------------------------------------------------- /test/cli/fixtures/only-module-flat.tap.txt: -------------------------------------------------------------------------------- 1 | # command: ["qunit", "only-module-flat.js"] 2 | 3 | TAP version 13 4 | not ok 1 module B > test B # TODO 5 | --- 6 | message: not implemented yet 7 | severity: todo 8 | actual : false 9 | expected: true 10 | stack: | 11 | at /qunit/test/cli/fixtures/only-module-flat.js:8:14 12 | ... 13 | ok 2 module B > test C # SKIP 14 | ok 3 module B > test D 15 | 1..4 16 | # pass 2 17 | # skip 1 18 | # todo 1 19 | # fail 0 20 | -------------------------------------------------------------------------------- /test/cli/fixtures/only-module-then-test.js: -------------------------------------------------------------------------------- 1 | // https://github.com/qunitjs/qunit/issues/1645 2 | QUnit.module('module A', function () { 3 | QUnit.test('test A1', function (assert) { 4 | assert.true(false, 'not run'); 5 | }); 6 | 7 | QUnit.module.only('module B', function () { 8 | QUnit.test('test B', function (assert) { 9 | assert.true(true, 'run'); 10 | }); 11 | }); 12 | 13 | QUnit.test.only('test A2', function (assert) { 14 | assert.true(false, 'not run'); 15 | }); 16 | 17 | QUnit.test('test A3', function (assert) { 18 | assert.true(false, 'not run'); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/cli/fixtures/only-module-then-test.tap.txt: -------------------------------------------------------------------------------- 1 | # name: module.only() followed by test 2 | # command: ["qunit", "only-module-then-test.js"] 3 | 4 | TAP version 13 5 | ok 1 module A > module B > test B 6 | 1..2 7 | # pass 2 8 | # skip 0 9 | # todo 0 10 | # fail 0 11 | -------------------------------------------------------------------------------- /test/cli/fixtures/only-module.tap.txt: -------------------------------------------------------------------------------- 1 | # name: module.only() nested 2 | # command: ["qunit", "only-module.js"] 3 | 4 | TAP version 13 5 | not ok 1 module B > Only this module should run > a todo test # TODO 6 | --- 7 | message: not implemented yet 8 | severity: todo 9 | actual : false 10 | expected: true 11 | stack: | 12 | at /qunit/test/cli/fixtures/only-module.js:16:18 13 | ... 14 | ok 2 module B > Only this module should run > implicitly skipped test # SKIP 15 | ok 3 module B > Only this module should run > normal test 16 | ok 4 module D > test D 17 | ok 5 module E > module F > test F 18 | ok 6 module E > test E 19 | 1..8 20 | # pass 6 21 | # skip 1 22 | # todo 1 23 | # fail 0 24 | -------------------------------------------------------------------------------- /test/cli/fixtures/only-test-only-module-mix.tap.txt: -------------------------------------------------------------------------------- 1 | # command: ["qunit", "only-test-only-module-mix.js"] 2 | 3 | TAP version 13 4 | not ok 1 global failure 5 | --- 6 | message: Error: No tests were run. 7 | severity: failed 8 | stack: | 9 | Error: No tests were run. 10 | ... 11 | Bail out! Error: No tests were run. 12 | 1..3 13 | # pass 2 14 | # skip 0 15 | # todo 0 16 | # fail 1 17 | 18 | # exit code: 1 19 | -------------------------------------------------------------------------------- /test/cli/fixtures/only-test.js: -------------------------------------------------------------------------------- 1 | QUnit.test('implicitly skipped test', function (assert) { 2 | assert.true(false, 'test should be skipped'); 3 | }); 4 | 5 | QUnit.only('run this test', function (assert) { 6 | assert.true(true, 'only this test should run'); 7 | }); 8 | 9 | QUnit.test('another implicitly skipped test', function (assert) { 10 | assert.true(false, 'test should be skipped'); 11 | }); 12 | 13 | QUnit.only('all tests with only run', function (assert) { 14 | assert.true(true, 'this test should run as well'); 15 | }); 16 | -------------------------------------------------------------------------------- /test/cli/fixtures/only-test.tap.txt: -------------------------------------------------------------------------------- 1 | # name: test.only() 2 | # command: ["qunit","only-test.js"] 3 | 4 | TAP version 13 5 | ok 1 run this test 6 | ok 2 all tests with only run 7 | 1..3 8 | # pass 3 9 | # skip 0 10 | # todo 0 11 | # fail 0 12 | -------------------------------------------------------------------------------- /test/cli/fixtures/pending-async-after-timeout.js: -------------------------------------------------------------------------------- 1 | // Regression test for https://github.com/qunitjs/qunit/issues/1705 2 | QUnit.test('example', async assert => { 3 | assert.timeout(10); 4 | // eslint-disable-next-line no-unused-vars 5 | const done = assert.async(); 6 | assert.true(true); 7 | }); 8 | -------------------------------------------------------------------------------- /test/cli/fixtures/pending-async-after-timeout.tap.txt: -------------------------------------------------------------------------------- 1 | # name: test with pending async after timeout 2 | # command: ["qunit", "pending-async-after-timeout.js"] 3 | 4 | TAP version 13 5 | not ok 1 example 6 | --- 7 | message: Test took longer than 10ms; test timed out. 8 | severity: failed 9 | ... 10 | 1..1 11 | # pass 0 12 | # skip 0 13 | # todo 0 14 | # fail 1 15 | 16 | # exit code: 1 17 | -------------------------------------------------------------------------------- /test/cli/fixtures/perf-mark.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | 3 | QUnit.config.reorder = false; 4 | 5 | QUnit.test('foo', function (assert) { 6 | assert.true(true); 7 | }); 8 | 9 | QUnit.test('bar', function (assert) { 10 | assert.true(true); 11 | }); 12 | 13 | QUnit.test('getEntries', function (assert) { 14 | const entries = performance.getEntriesByType('measure') 15 | .filter(function (entry) { 16 | return entry.name.indexOf('QUnit') === 0; 17 | }) 18 | .map(function (entry) { 19 | return entry.toJSON(); 20 | }); 21 | 22 | assert.propContains(entries, [ 23 | { name: 'QUnit Test: foo' }, 24 | { name: 'QUnit Test: bar' } 25 | ]); 26 | }); 27 | -------------------------------------------------------------------------------- /test/cli/fixtures/perf-mark.tap.txt: -------------------------------------------------------------------------------- 1 | # command: ["qunit", "perf-mark.js"] 2 | # env: { "qunit_config_reporters_perf": true } 3 | 4 | TAP version 13 5 | ok 1 foo 6 | ok 2 bar 7 | ok 3 getEntries 8 | 1..3 9 | # pass 3 10 | # skip 0 11 | # todo 0 12 | # fail 0 -------------------------------------------------------------------------------- /test/cli/fixtures/preconfig-flat.js: -------------------------------------------------------------------------------- 1 | QUnit.test('config', function (assert) { 2 | assert.strictEqual(QUnit.config.maxDepth, 5, 'maxDepth default'); 3 | assert.strictEqual(QUnit.config.filter, '!foobar', 'filter'); 4 | assert.strictEqual(QUnit.config.seed, 'dummyfirstyes', 'seed'); 5 | assert.strictEqual(QUnit.config.testTimeout, 7, 'testTimeout'); 6 | 7 | // readFlatPreconfigBoolean 8 | assert.strictEqual(QUnit.config.altertitle, true, 'altertitle "true"'); 9 | assert.strictEqual(QUnit.config.noglobals, true, 'noglobals "1"'); 10 | assert.strictEqual(QUnit.config.notrycatch, false, 'notrycatch "false"'); 11 | }); 12 | 13 | QUnit.test('dummy', function (assert) { 14 | // have at least two tests so that output demonstrates 15 | // the effect of the seed on test order, 16 | assert.true(true); 17 | }); 18 | 19 | QUnit.test('slow', function (assert) { 20 | assert.true(true); 21 | return new Promise(resolve => setTimeout(resolve, 1000)); 22 | }); 23 | 24 | QUnit.test('foobar', function (assert) { 25 | assert.false(true, 'foobar test skipped by filter'); 26 | }); 27 | -------------------------------------------------------------------------------- /test/cli/fixtures/preconfig-flat.tap.txt: -------------------------------------------------------------------------------- 1 | # command: ["qunit", "preconfig-flat.js"] 2 | # env: { "qunit_config_filter": "!foobar", "qunit_config_seed": "dummyfirstyes", "qunit_config_testtimeout": 7, "qunit_config_altertitle": "true", "qunit_config_noglobals": 1, "qunit_config_notrycatch": "false" } 3 | 4 | Running tests with seed: dummyfirstyes 5 | TAP version 13 6 | ok 1 dummy 7 | not ok 2 slow 8 | --- 9 | message: Test took longer than 7ms; test timed out. 10 | severity: failed 11 | ... 12 | ok 3 config 13 | 1..3 14 | # pass 2 15 | # skip 0 16 | # todo 0 17 | # fail 1 18 | 19 | # exit code: 1 -------------------------------------------------------------------------------- /test/cli/fixtures/require-module-and-script.tap.txt: -------------------------------------------------------------------------------- 1 | # name: --require loads dependency and script 2 | # command: ["qunit","basic-one.js","--require","require-dep","--require","./node_modules/require-dep/module.js"] 3 | 4 | required require-dep/index.js 5 | required require-dep/module.js 6 | TAP version 13 7 | ok 1 Single > has a test 8 | 1..1 9 | # pass 1 10 | # skip 0 11 | # todo 0 12 | # fail 0 13 | -------------------------------------------------------------------------------- /test/cli/fixtures/seed.tap.txt: -------------------------------------------------------------------------------- 1 | # name: --seed value 2 | # command: ["qunit", "--seed", "s33d", "test", "basic-one.js", "glob/**/*-test.js"] 3 | 4 | Running tests with seed: s33d 5 | TAP version 13 6 | ok 1 Second > 1 7 | ok 2 Extension MJS > example 8 | ok 3 Nested-Test > herp 9 | ok 4 Extension CJS > example 10 | ok 5 A-Test > derp 11 | ok 6 First > 1 12 | ok 7 Single > has a test 13 | 1..7 14 | # pass 7 15 | # skip 0 16 | # todo 0 17 | # fail 0 18 | -------------------------------------------------------------------------------- /test/cli/fixtures/sourcemap/source.js: -------------------------------------------------------------------------------- 1 | QUnit.module('Example', function () { 2 | QUnit.test('good', function (assert) { 3 | assert.true(true); 4 | }); 5 | 6 | QUnit.test('bad', function (assert) { 7 | assert.true(false); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/cli/fixtures/sourcemap/source.min.js: -------------------------------------------------------------------------------- 1 | QUnit.module("Example",function(){QUnit.test("good",function(assert){assert.true(!0)}),QUnit.test("bad",function(assert){assert.true(!1)})}); 2 | //# sourceMappingURL=source.min.js.map -------------------------------------------------------------------------------- /test/cli/fixtures/sourcemap/source.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["sourcemap/source.js"],"names":["QUnit","module","test","assert","true"],"mappings":"AAAAA,MAAMC,OAAQ,UAAW,WACxBD,MAAME,KAAM,OAAQ,SAAUC,QAC7BA,OAAOC,MAAM,KAGdJ,MAAME,KAAM,MAAO,SAAUC,QAC5BA,OAAOC,MAAM"} -------------------------------------------------------------------------------- /test/cli/fixtures/syntax-error.js: -------------------------------------------------------------------------------- 1 | varIsNotDefined; // eslint-disable-line 2 | -------------------------------------------------------------------------------- /test/cli/fixtures/syntax-error.tap.txt: -------------------------------------------------------------------------------- 1 | # name: load file with syntax error 2 | # command: ["qunit", "syntax-error.js"] 3 | 4 | TAP version 13 5 | not ok 1 global failure 6 | --- 7 | message: |+ 8 | Error: Failed to load file syntax-error.js 9 | ReferenceError: varIsNotDefined is not defined 10 | severity: failed 11 | stack: | 12 | ReferenceError: varIsNotDefined is not defined 13 | at /qunit/test/cli/fixtures/syntax-error.js:1:1 14 | at internal 15 | ... 16 | Bail out! Error: Failed to load file syntax-error.js 17 | 1..2 18 | # pass 0 19 | # skip 0 20 | # todo 0 21 | # fail 2 22 | 23 | # exit code: 1 24 | -------------------------------------------------------------------------------- /test/cli/fixtures/test-if.js: -------------------------------------------------------------------------------- 1 | QUnit.test.if('skip me', false, function (assert) { 2 | assert.true(false); 3 | }); 4 | 5 | QUnit.test.if('keep me', true, function (assert) { 6 | assert.true(true); 7 | }); 8 | 9 | QUnit.test('regular', function (assert) { 10 | assert.true(true); 11 | }); 12 | 13 | QUnit.test.if.each('skip dataset', false, ['a', 'b'], function (assert, _data) { 14 | assert.true(false); 15 | }); 16 | 17 | QUnit.test.if.each('keep dataset', true, ['a', 'b'], function (assert, data) { 18 | assert.true(true); 19 | assert.equal(typeof data, 'string'); 20 | }); 21 | 22 | QUnit.module.if('skip group', false, function () { 23 | QUnit.test('skipper', function (assert) { 24 | assert.true(false); 25 | }); 26 | }); 27 | 28 | QUnit.module.if('keep group', true, function (hooks) { 29 | let list = []; 30 | hooks.beforeEach(function () { 31 | list.push('x'); 32 | }); 33 | QUnit.test('keeper', function (assert) { 34 | assert.true(true); 35 | assert.deepEqual(list, ['x']); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/cli/fixtures/test-if.tap.txt: -------------------------------------------------------------------------------- 1 | # name: no tests 2 | # command: ["qunit", "test-if.js"] 3 | 4 | TAP version 13 5 | ok 1 skip me # SKIP 6 | ok 2 keep me 7 | ok 3 regular 8 | ok 4 skip dataset [a] # SKIP 9 | ok 5 skip dataset [b] # SKIP 10 | ok 6 keep dataset [a] 11 | ok 7 keep dataset [b] 12 | ok 8 skip group > skipper # SKIP 13 | ok 9 keep group > keeper 14 | 1..9 15 | # pass 5 16 | # skip 4 17 | # todo 0 18 | # fail 0 19 | -------------------------------------------------------------------------------- /test/cli/fixtures/test/extension.cjs: -------------------------------------------------------------------------------- 1 | QUnit.module('Extension CJS', function () { 2 | QUnit.test('example', function (assert) { 3 | assert.true(true); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /test/cli/fixtures/test/extension.mjs: -------------------------------------------------------------------------------- 1 | QUnit.module('Extension MJS', function () { 2 | QUnit.test('example', function (assert) { 3 | assert.true(true); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /test/cli/fixtures/test/extension.ts: -------------------------------------------------------------------------------- 1 | throw new Error('Directory scan should not load TS by default.'); 2 | -------------------------------------------------------------------------------- /test/cli/fixtures/test/extension.txt: -------------------------------------------------------------------------------- 1 | Directory scan should not load TXT by default. 2 | -------------------------------------------------------------------------------- /test/cli/fixtures/test/first.js: -------------------------------------------------------------------------------- 1 | QUnit.module('First', function () { 2 | QUnit.test('1', function (assert) { 3 | assert.true(true); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /test/cli/fixtures/test/nested/second.js: -------------------------------------------------------------------------------- 1 | QUnit.module('Second', function () { 2 | QUnit.test('1', function (assert) { 3 | assert.true(true); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /test/cli/fixtures/timeout.js: -------------------------------------------------------------------------------- 1 | QUnit.module('timeout', function () { 2 | // This should fail 3 | QUnit.test('first', function (assert) { 4 | assert.timeout(10); 5 | 6 | return new Promise(resolve => setTimeout(resolve, 20)); 7 | }); 8 | 9 | // Runner should recover and still run and pass this test 10 | QUnit.test('second', function (assert) { 11 | return new Promise(resolve => setTimeout(resolve, 20)) 12 | .then(() => { 13 | assert.true(true); 14 | }); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /test/cli/fixtures/timeout.tap.txt: -------------------------------------------------------------------------------- 1 | # name: two tests with one timeout 2 | # command: ["qunit", "timeout.js"] 3 | 4 | TAP version 13 5 | not ok 1 timeout > first 6 | --- 7 | message: Test took longer than 10ms; test timed out. 8 | severity: failed 9 | ... 10 | ok 2 timeout > second 11 | 1..2 12 | # pass 1 13 | # skip 0 14 | # todo 0 15 | # fail 1 16 | 17 | # exit code: 1 18 | -------------------------------------------------------------------------------- /test/cli/fixtures/too-many-done-calls.js: -------------------------------------------------------------------------------- 1 | QUnit.test('Test A', assert => { 2 | assert.ok(true); 3 | const done = assert.async(); 4 | done(); 5 | done(); 6 | }); 7 | -------------------------------------------------------------------------------- /test/cli/fixtures/too-many-done-calls.tap.txt: -------------------------------------------------------------------------------- 1 | # name: assert.async() handled too often 2 | # command: ["qunit", "too-many-done-calls.js"] 3 | 4 | TAP version 13 5 | not ok 1 Test A 6 | --- 7 | message: |+ 8 | Died on test #2: Tried to release async pause that was already released. 9 | > Test: Test A [async #1] 10 | at /qunit/test/cli/fixtures/too-many-done-calls.js:1:7 11 | at internal 12 | severity: failed 13 | stack: | 14 | Error: Tried to release async pause that was already released. 15 | > Test: Test A [async #1] 16 | ... 17 | 1..1 18 | # pass 0 19 | # skip 0 20 | # todo 0 21 | # fail 1 22 | 23 | # exit code: 1 24 | -------------------------------------------------------------------------------- /test/cli/fixtures/uncaught-error-after-assert-async.js: -------------------------------------------------------------------------------- 1 | QUnit.test('contains a hard error after using assert.async()', assert => { 2 | assert.async(); 3 | assert.true(true); 4 | throw new Error('expected error thrown in test'); 5 | 6 | // the "done" callback from `assert.async` should be called later, 7 | // but the hard-error prevents the test from reaching that 8 | }); 9 | -------------------------------------------------------------------------------- /test/cli/fixtures/uncaught-error-after-assert-async.tap.txt: -------------------------------------------------------------------------------- 1 | # name: uncaught error after assert.async() 2 | # command: ["qunit", "uncaught-error-after-assert-async.js"] 3 | 4 | TAP version 13 5 | not ok 1 contains a hard error after using assert.async() 6 | --- 7 | message: |+ 8 | Died on test #2: expected error thrown in test 9 | at /qunit/test/cli/fixtures/uncaught-error-after-assert-async.js:1:7 10 | at internal 11 | severity: failed 12 | stack: | 13 | Error: expected error thrown in test 14 | at /qunit/test/cli/fixtures/uncaught-error-after-assert-async.js:4:9 15 | ... 16 | 1..1 17 | # pass 0 18 | # skip 0 19 | # todo 0 20 | # fail 1 21 | 22 | # exit code: 1 23 | -------------------------------------------------------------------------------- /test/cli/fixtures/uncaught-error-callback-moduleDone.js: -------------------------------------------------------------------------------- 1 | QUnit.moduleDone(details => { 2 | throw new Error('No dice for ' + details.name); 3 | }); 4 | 5 | QUnit.module('module1', () => { 6 | QUnit.test('test1', assert => { 7 | assert.true(true); 8 | }); 9 | }); 10 | 11 | QUnit.module('module2', () => { 12 | QUnit.test('test2', assert => { 13 | assert.true(true); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/cli/fixtures/uncaught-error-callback-moduleDone.tap.txt: -------------------------------------------------------------------------------- 1 | # name: uncaught error in "moduleDone" callback 2 | # command: ["qunit","uncaught-error-callback-moduleDone.js"] 3 | 4 | TAP version 13 5 | ok 1 module1 > test1 6 | 7 | # stderr 8 | Error: Process exited before tests finished running 9 | 10 | # exit code: 1 11 | -------------------------------------------------------------------------------- /test/cli/fixtures/uncaught-error-callback-testStart.js: -------------------------------------------------------------------------------- 1 | QUnit.testStart(details => { 2 | throw new Error('No dice for ' + details.name); 3 | }); 4 | 5 | QUnit.module('module1', () => { 6 | QUnit.test('test1', assert => { 7 | assert.true(true); 8 | }); 9 | }); 10 | 11 | QUnit.module('module2', () => { 12 | QUnit.test('test2', assert => { 13 | assert.true(true); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/cli/fixtures/uncaught-error-callback-testStart.tap.txt: -------------------------------------------------------------------------------- 1 | # name: uncaught error in "testStart" callback 2 | # command: ["qunit","uncaught-error-callback-testStart.js"] 3 | 4 | TAP version 13 5 | 6 | # stderr 7 | Error: Process exited before tests finished running 8 | 9 | # exit code: 1 10 | -------------------------------------------------------------------------------- /test/cli/fixtures/uncaught-error-callbacks-begin.js: -------------------------------------------------------------------------------- 1 | QUnit.begin(() => { 2 | throw new Error('No dice'); 3 | }); 4 | 5 | QUnit.module('module1', () => { 6 | QUnit.test('test1', assert => { 7 | assert.true(true); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/cli/fixtures/uncaught-error-callbacks-begin.tap.txt: -------------------------------------------------------------------------------- 1 | # name: uncaught error in "begin" callback 2 | # command: ["qunit", "uncaught-error-callbacks-begin.js"] 3 | 4 | TAP version 13 5 | not ok 1 global failure 6 | --- 7 | message: Error: No dice 8 | severity: failed 9 | stack: | 10 | Error: No dice 11 | at /qunit/test/cli/fixtures/uncaught-error-callbacks-begin.js:2:9 12 | at qunit.js 13 | at internal 14 | ... 15 | Bail out! Error: No dice 16 | 17 | # stderr 18 | Error: Process exited before tests finished running 19 | 20 | # exit code: 1 21 | -------------------------------------------------------------------------------- /test/cli/fixtures/uncaught-error-callbacks-done.js: -------------------------------------------------------------------------------- 1 | QUnit.done(() => { 2 | throw new Error('No dice'); 3 | }); 4 | 5 | QUnit.module('module1', () => { 6 | QUnit.test('test1', assert => { 7 | assert.true(true); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/cli/fixtures/uncaught-error-callbacks-done.tap.txt: -------------------------------------------------------------------------------- 1 | # name: uncaught error in "done" callback 2 | # command: ["qunit", "uncaught-error-callbacks-done.js"] 3 | 4 | TAP version 13 5 | ok 1 module1 > test1 6 | 1..1 7 | # pass 1 8 | # skip 0 9 | # todo 0 10 | # fail 0 11 | Bail out! Error: No dice 12 | --- 13 | message: Error: No dice 14 | severity: failed 15 | stack: | 16 | Error: No dice 17 | at /qunit/test/cli/fixtures/uncaught-error-callbacks-done.js:2:9 18 | at qunit.js 19 | at internal 20 | ... 21 | 22 | # exit code: 1 23 | -------------------------------------------------------------------------------- /test/cli/fixtures/uncaught-error-in-hook.js: -------------------------------------------------------------------------------- 1 | QUnit.module('contains a hard error in hook', hooks => { 2 | hooks.before(() => { 3 | throw new Error('expected error thrown in hook'); 4 | }); 5 | QUnit.test('contains a hard error', assert => { 6 | assert.true(true); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /test/cli/fixtures/uncaught-error-in-hook.tap.txt: -------------------------------------------------------------------------------- 1 | # name: uncaught error in hook 2 | # command: ["qunit", "uncaught-error-in-hook.js"] 3 | 4 | TAP version 13 5 | not ok 1 contains a hard error in hook > contains a hard error 6 | --- 7 | message: before failed on contains a hard error: expected error thrown in hook 8 | severity: failed 9 | stack: | 10 | Error: expected error thrown in hook 11 | at /qunit/test/cli/fixtures/uncaught-error-in-hook.js:3:11 12 | ... 13 | 1..1 14 | # pass 0 15 | # skip 0 16 | # todo 0 17 | # fail 1 18 | 19 | # exit code: 1 20 | -------------------------------------------------------------------------------- /test/cli/fixtures/unhandled-rejection.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | QUnit.module('Unhandled Rejections', function () { 4 | QUnit.test('test passes just fine, but has a rejected promise', function (assert) { 5 | assert.true(true); 6 | 7 | const done = assert.async(); 8 | 9 | Promise.resolve().then(function () { 10 | throw new Error('Error thrown in non-returned promise!'); 11 | }); 12 | 13 | // prevent test from exiting before unhandled rejection fires 14 | setTimeout(done, 10); 15 | }); 16 | 17 | Promise.reject(new Error('outside of a test context')); 18 | }); 19 | -------------------------------------------------------------------------------- /test/cli/fixtures/unhandled-rejection.tap.txt: -------------------------------------------------------------------------------- 1 | # name: unhandled rejection 2 | # command: ["qunit","unhandled-rejection.js"] 3 | 4 | TAP version 13 5 | not ok 1 global failure 6 | --- 7 | message: Error: outside of a test context 8 | severity: failed 9 | stack: | 10 | Error: outside of a test context 11 | at /qunit/test/cli/fixtures/unhandled-rejection.js:17:18 12 | at qunit.js 13 | at /qunit/test/cli/fixtures/unhandled-rejection.js:3:7 14 | at internal 15 | ... 16 | Bail out! Error: outside of a test context 17 | not ok 2 Unhandled Rejections > test passes just fine, but has a rejected promise 18 | --- 19 | message: global failure: Error: Error thrown in non-returned promise! 20 | severity: failed 21 | stack: | 22 | Error: Error thrown in non-returned promise! 23 | at /qunit/test/cli/fixtures/unhandled-rejection.js:10:13 24 | ... 25 | 1..2 26 | # pass 0 27 | # skip 0 28 | # todo 0 29 | # fail 2 30 | 31 | # exit code: 1 32 | -------------------------------------------------------------------------------- /test/cli/fixtures/zero-assertions.js: -------------------------------------------------------------------------------- 1 | QUnit.module('Zero assertions', function () { 2 | QUnit.test('has a test', function (assert) { 3 | assert.expect(0); 4 | 5 | // A test may expect zero assertions if its main purpose 6 | // is to ensure there are no no run-time exceptions. 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /test/cli/fixtures/zero-assertions.tap.txt: -------------------------------------------------------------------------------- 1 | # name: test with zero assertions 2 | # command: ["qunit", "zero-assertions.js"] 3 | 4 | TAP version 13 5 | ok 1 Zero assertions > has a test 6 | 1..1 7 | # pass 1 8 | # skip 0 9 | # todo 0 10 | # fail 0 11 | -------------------------------------------------------------------------------- /test/dynamic-import.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QUnit 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/dynamic-import/bar.js: -------------------------------------------------------------------------------- 1 | QUnit.module('bar', function () { 2 | QUnit.test('example', function (assert) { 3 | assert.true(true); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /test/dynamic-import/foo.js: -------------------------------------------------------------------------------- 1 | QUnit.module('foo', function () { 2 | QUnit.test('example', function (assert) { 3 | assert.true(true); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /test/dynamic-import/index.js: -------------------------------------------------------------------------------- 1 | QUnit.config.autostart = false; 2 | 3 | Promise.all([ 4 | import('./foo.js'), 5 | import('./bar.js') 6 | ]).then(function () { 7 | QUnit.start(); 8 | }); 9 | -------------------------------------------------------------------------------- /test/dynamic-import/sum.mjs: -------------------------------------------------------------------------------- 1 | function sum (a, b) { 2 | return a + b; 3 | } 4 | 5 | export default sum; 6 | -------------------------------------------------------------------------------- /test/events-filters.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | events-filters 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/events-in-test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | events-in-test 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/logs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | logs 6 | 7 | 8 | 12 | 13 | 14 | 15 |
16 |
test markup
17 | 18 | 19 | -------------------------------------------------------------------------------- /test/main/callbacks.js: -------------------------------------------------------------------------------- 1 | QUnit.module('callbacks', function () { 2 | QUnit.test('QUnit.testDone [failure]', function (assert) { 3 | assert.throws(function () { 4 | QUnit.testDone(undefined); 5 | }, TypeError, 'undefined callback'); 6 | 7 | assert.throws(function () { 8 | QUnit.testDone(null); 9 | }, TypeError, 'null callback'); 10 | 11 | assert.throws(function () { 12 | QUnit.testDone('banana'); 13 | }, TypeError, 'string callback'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/main/events.js: -------------------------------------------------------------------------------- 1 | QUnit.module('events', function () { 2 | QUnit.test('QUnit.on [failure]', function (assert) { 3 | assert.throws(function () { 4 | QUnit.on(null, function () { 5 | assert.step('null called'); 6 | }); 7 | }, /must be a string/, 'null event name'); 8 | 9 | assert.throws(function () { 10 | QUnit.on('banana', function () { 11 | assert.step('banana called'); 12 | }); 13 | }, /not a valid event/, 'unknown event name'); 14 | 15 | assert.throws(function () { 16 | QUnit.on('runStart'); 17 | }, /must be a function/, 'missing callback'); 18 | 19 | assert.throws(function () { 20 | QUnit.on('runStart', null); 21 | }, /must be a function/, 'null callback'); 22 | 23 | assert.verifySteps([]); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/main/modules-esm.mjs: -------------------------------------------------------------------------------- 1 | import sum from '../dynamic-import/sum.mjs'; 2 | 3 | QUnit.module('modules [esm]', () => { 4 | QUnit.test('example', assert => { 5 | assert.equal(5, sum(2, 3)); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /test/main/setTimeout.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | // eslint-disable-next-line no-undef 3 | var global = typeof globalThis !== 'undefined' ? globalThis : window; 4 | QUnit.module('Support for mocked setTimeout', { 5 | beforeEach: function () { 6 | this.setTimeout = global.setTimeout; 7 | global.setTimeout = function () {}; 8 | }, 9 | 10 | afterEach: function () { 11 | global.setTimeout = this.setTimeout; 12 | } 13 | }); 14 | 15 | QUnit.test('test one', function (assert) { 16 | assert.true(true); 17 | }); 18 | 19 | QUnit.test('test two', function (assert) { 20 | assert.true(true); 21 | }); 22 | }()); 23 | -------------------------------------------------------------------------------- /test/module-skip.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | module-skip 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /test/module-todo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | module-todo 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /test/node/storage-1.js: -------------------------------------------------------------------------------- 1 | var lastTest = ''; 2 | var mockStorage = require('./storage.js'); 3 | 4 | mockStorage.setItem('qunit-test-Storage #1-Should be run first', 1); 5 | QUnit.config.storage = mockStorage; 6 | 7 | QUnit.module('Storage #1', function () { 8 | QUnit.test('Passing test', function (assert) { 9 | assert.strictEqual(lastTest, 'Should be run first', 'test is run second'); 10 | mockStorage.setItem('qunit-test-Storage #1-Passing test', true); 11 | }); 12 | 13 | QUnit.test('Removes passing tests from storage', function (assert) { 14 | assert.strictEqual(mockStorage.getItem('qunit-test-Storage #1-Passing test'), null); 15 | }); 16 | 17 | // Verifies test reordering by storage values 18 | QUnit.test('Should be run first', function (assert) { 19 | assert.strictEqual(lastTest, ''); 20 | lastTest = 'Should be run first'; 21 | }); 22 | }); 23 | 24 | QUnit.done(function () { 25 | mockStorage.setItem('qunit-test-should-remove', true); 26 | mockStorage.setItem('should-not-remove', true); 27 | mockStorage.setItem('qunit-test-should-also-remove', true); 28 | }); 29 | -------------------------------------------------------------------------------- /test/node/storage-2.js: -------------------------------------------------------------------------------- 1 | var mockStorage = require('./storage.js'); 2 | 3 | QUnit.module('Storage #2', function () { 4 | QUnit.test('clears all qunit-test-* items after a successful run', function (assert) { 5 | assert.strictEqual( 6 | mockStorage.getItem('should-not-remove'), 7 | true, 8 | 'state was persisted from last test' 9 | ); 10 | assert.strictEqual( 11 | mockStorage.getItem('qunit-test-should-remove'), 12 | null, 13 | 'removed first test' 14 | ); 15 | assert.strictEqual( 16 | mockStorage.getItem('qunit-test-should-also-remove'), 17 | null, 18 | 'removed second test' 19 | ); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/node/storage.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | _store: Object.create(null), 3 | setItem: function (key, value) { 4 | this._store[key] = value; 5 | }, 6 | getItem: function (key) { 7 | return key in this._store ? this._store[key] : null; 8 | }, 9 | removeItem: function (key) { 10 | if (key in this._store) { 11 | delete this._store[key]; 12 | } 13 | }, 14 | key: function (i) { 15 | return Object.keys(this._store)[i]; 16 | }, 17 | get length () { 18 | return Object.keys(this._store).length; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /test/only-each.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | only-each 6 | 7 | 8 | 9 | 10 | 11 |
12 |
test markup
13 | 14 | 15 | -------------------------------------------------------------------------------- /test/only-each.js: -------------------------------------------------------------------------------- 1 | QUnit.module.only('test.each.only', function () { 2 | QUnit.test("don't run", function (assert) { assert.true(false); }); 3 | QUnit.test.only.each('test.each.only', [[1, 2, 3], [1, 1, 2]], function (assert, data) { 4 | assert.strictEqual(data[0] + data[1], data[2]); 5 | }); 6 | QUnit.test.only.each('test.each.only 1D', [1, [], 'some'], function (assert, value) { 7 | assert.true(Boolean(value)); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/overload.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | overload 6 | 7 | 15 | 16 | 17 | 18 | 30 | 31 | 32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /test/perf-clear-marks.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | perf-clear-marks 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /test/perf-clear-marks.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | QUnit.module('urlParams performance mark module', function () { 3 | QUnit.test("shouldn't fail if performance marks are cleared", function (assert) { 4 | // Optional feature available in IE10+ and Safari 10+ 5 | // eslint-disable-next-line compat/compat 6 | performance.clearMarks(); 7 | 8 | assert.true(true); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/perf-mark.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | perf-mark 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /test/perf-mark.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | 3 | QUnit.config.reorder = false; 4 | 5 | QUnit.test('foo', function (assert) { 6 | assert.true(true); 7 | }); 8 | 9 | QUnit.test('bar', function (assert) { 10 | assert.true(true); 11 | }); 12 | 13 | QUnit.test('getEntries', function (assert) { 14 | // eslint-disable-next-line compat/compat -- Only for IE 10+ and Safari 10+ 15 | var entries = performance.getEntriesByType('measure') 16 | .filter(function (entry) { 17 | return entry.name.indexOf('QUnit') === 0; 18 | }) 19 | .map(function (entry) { 20 | return entry.toJSON(); 21 | }); 22 | 23 | assert.propContains(entries, [ 24 | { name: 'QUnit Test: foo' }, 25 | { name: 'QUnit Test: bar' } 26 | ]); 27 | }); 28 | -------------------------------------------------------------------------------- /test/preconfig-flat-testId.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | preconfig-flat-testId 6 | 7 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /test/preconfig-flat-testId.js: -------------------------------------------------------------------------------- 1 | QUnit.test('test 1', function (assert) { 2 | assert.true(false); 3 | }); 4 | 5 | QUnit.test('test 2', function (assert) { 6 | assert.true(true, 'run test 2'); 7 | assert.deepEqual( 8 | QUnit.config.testId, 9 | ['94e5e740'], 10 | 'QUnit.config.testId' 11 | ); 12 | }); 13 | 14 | QUnit.test('test 3', function (assert) { 15 | assert.true(false); 16 | }); 17 | -------------------------------------------------------------------------------- /test/preconfig-flat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | preconfig-flat 6 | 7 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /test/preconfig-flat.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | QUnit.module('QUnit.config [preconfigured]'); 3 | 4 | QUnit.test('config', function (assert) { 5 | assert.strictEqual(QUnit.config.maxDepth, 5, 'maxDepth default'); 6 | assert.false(QUnit.config.autostart, 'autostart'); 7 | assert.strictEqual(QUnit.config.seed, 'd84af39036', 'seed'); 8 | 9 | // readFlatPreconfigBoolean 10 | assert.strictEqual(QUnit.config.altertitle, true, 'altertitle "true"'); 11 | assert.strictEqual(QUnit.config.noglobals, true, 'noglobals "1"'); 12 | assert.strictEqual(QUnit.config.notrycatch, false, 'notrycatch "false"'); 13 | }); 14 | 15 | window.addEventListener('load', function () { 16 | setTimeout(function () { 17 | QUnit.start(); 18 | }, 1); 19 | }); 20 | -------------------------------------------------------------------------------- /test/preconfig-object.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | preconfig-object 6 | 7 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /test/preconfig-object.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | QUnit.module('QUnit.config [preconfigured]'); 3 | 4 | QUnit.test('config', function (assert) { 5 | assert.strictEqual(QUnit.config.maxDepth, 5, 'maxDepth default'); 6 | assert.false(QUnit.config.autostart, 'autostart override'); 7 | assert.false(QUnit.config.reorder, 'reorder override'); 8 | }); 9 | 10 | window.addEventListener('load', function () { 11 | setTimeout(function () { 12 | QUnit.start(); 13 | }, 1); 14 | }); 15 | -------------------------------------------------------------------------------- /test/reorder.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | reorder 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /test/reorderError1.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | QUnit.module('Test call count - first case'); 3 | QUnit.test.if( 4 | 'does not skip tests after reordering', 5 | !!window.sessionStorage, 6 | function (assert) { 7 | assert.equal(window.totalCount, 3); 8 | } 9 | ); 10 | -------------------------------------------------------------------------------- /test/reorderError2.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | QUnit.module('Test call count - second case'); 3 | QUnit.test.if( 4 | 'does not skip tests after reordering', 5 | !!window.sessionStorage, 6 | function (assert) { 7 | assert.equal(window.totalCount, 2); 8 | } 9 | ); 10 | -------------------------------------------------------------------------------- /test/reporter-urlparams.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | reporter-urlparams 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /test/sandboxed-iframe--contents.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | sandboxed-iframe-contents 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /test/sandboxed-iframe.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | 3 | window.parent.postMessage('hello', '*'); 4 | 5 | QUnit.on('testEnd', function (testEnd) { 6 | window.parent.postMessage( 7 | 'testEnd: ' + testEnd.name, 8 | '*' 9 | ); 10 | }); 11 | 12 | QUnit.on('runEnd', function (runEnd) { 13 | window.parent.postMessage( 14 | 'runEnd: status=' + runEnd.status + ', total=' + runEnd.testCounts.total, 15 | '*' 16 | ); 17 | }); 18 | 19 | QUnit.module('sandboxed', function () { 20 | QUnit.test('foo', function (assert) { 21 | assert.true(false); 22 | }); 23 | 24 | QUnit.test.only('bar', function (assert) { 25 | assert.true(true); 26 | }); 27 | 28 | QUnit.test.skip('quux', function (assert) { 29 | assert.true(false); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/seed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | seed 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /test/seed.js: -------------------------------------------------------------------------------- 1 | QUnit.config.seed = '7x9'; 2 | 3 | var lastTest = ''; 4 | 5 | QUnit.module('QUnit.config.seed'); 6 | 7 | QUnit.test('1', function (assert) { 8 | assert.equal(lastTest, '2', 'runs third'); 9 | lastTest = '1'; 10 | }); 11 | 12 | QUnit.test('2', function (assert) { 13 | assert.equal(lastTest, '3', 'runs second'); 14 | lastTest = '2'; 15 | }); 16 | 17 | QUnit.test('3', function (assert) { 18 | assert.equal(lastTest, '', 'runs first'); 19 | lastTest = '3'; 20 | }); 21 | 22 | QUnit.test('4', function (assert) { 23 | assert.equal(lastTest, '1', 'runs last'); 24 | lastTest = '4'; 25 | }); 26 | -------------------------------------------------------------------------------- /test/startError.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | startError 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/urlparams-filter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QUnit 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/urlparams-filter.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | if (!location.search) { 3 | // regular expression (case-sensitive), inverted 4 | location.replace('?filter=!/Foo|bar/'); 5 | } 6 | 7 | QUnit.module('filter'); 8 | 9 | QUnit.test('config parsed', function (assert) { 10 | assert.strictEqual(QUnit.config.filter, '!/Foo|bar/'); 11 | }); 12 | 13 | QUnit.test('foo test', function (assert) { 14 | assert.true(true); 15 | }); 16 | 17 | QUnit.test('Foo test', function (assert) { 18 | assert.true(false, 'Foo is excluded'); 19 | }); 20 | 21 | QUnit.test('bar test', function (assert) { 22 | assert.true(false, 'bar is excluded'); 23 | }); 24 | 25 | QUnit.test('Bar test', function (assert) { 26 | assert.true(true); 27 | }); 28 | -------------------------------------------------------------------------------- /test/urlparams-module.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QUnit 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/urlparams-module.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | if (!location.search) { 3 | location.replace('?module=Foo'); 4 | } 5 | 6 | QUnit.module('Foo'); 7 | 8 | QUnit.test('config parsed', function (assert) { 9 | assert.strictEqual(QUnit.config.module, 'Foo', 'parsed config'); 10 | }); 11 | 12 | QUnit.module('Bar'); 13 | 14 | QUnit.test('Bar test', function (assert) { 15 | assert.true(false); 16 | }); 17 | -------------------------------------------------------------------------------- /test/urlparams-moduleId.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QUnit 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/urlparams-moduleId.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | if (!location.search) { 3 | location.replace('?moduleId=4dea3fbe&moduleId=9bf7d15c'); 4 | } 5 | 6 | QUnit.test('global test', function (assert) { 7 | assert.true(false); 8 | }); 9 | 10 | QUnit.module('module A scoped', function () { 11 | QUnit.test('test A1', function (assert) { 12 | assert.true(false); 13 | }); 14 | 15 | QUnit.module('module B nested', function () { 16 | QUnit.test('test B1', function (assert) { 17 | assert.true(true, 'run module B'); 18 | }); 19 | }); 20 | }); 21 | 22 | QUnit.module('module D flat'); 23 | QUnit.test('test D1', function (assert) { 24 | assert.true(false); 25 | }); 26 | 27 | QUnit.module('module E flat'); 28 | QUnit.test('test E1', function (assert) { 29 | assert.true(true, 'run module E'); 30 | assert.deepEqual( 31 | QUnit.config.moduleId, 32 | ['4dea3fbe', '9bf7d15c'], 33 | 'parsed config' 34 | ); 35 | }); 36 | -------------------------------------------------------------------------------- /test/urlparams-testId.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QUnit 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/urlparams-testId.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | if (!location.search) { 3 | location.replace('?testId=94e5e740'); 4 | } 5 | 6 | QUnit.test('test 1', function (assert) { 7 | assert.true(false); 8 | }); 9 | 10 | QUnit.test('test 2', function (assert) { 11 | assert.true(true, 'run global test 2'); 12 | assert.deepEqual( 13 | QUnit.config.testId, 14 | ['94e5e740'], 15 | 'parsed config' 16 | ); 17 | }); 18 | 19 | QUnit.test('test 3', function (assert) { 20 | assert.true(false); 21 | }); 22 | -------------------------------------------------------------------------------- /test/webWorker-worker.js: -------------------------------------------------------------------------------- 1 | // This worker script gets run via test/webWorker.html 2 | 3 | /* eslint-env worker */ 4 | 5 | importScripts( 6 | '../qunit/qunit.js', 7 | 8 | // Sync with test/index.html 9 | 'main/assert.js', 10 | 'main/assert-es6.js', 11 | 'main/assert-step.js', 12 | 'main/assert-timeout.js', 13 | 'main/async.js', 14 | 'main/browser-runner.js', 15 | 'main/callbacks.js', 16 | 'main/deepEqual.js', 17 | 'main/diff.js', 18 | 'main/dump.js', 19 | 'main/each.js', 20 | 'main/events.js', 21 | 'main/HtmlReporter.js', 22 | 'main/modules.js', 23 | 'main/modules-es2018.js', 24 | // TODO: 'main/modules-esm.mjs', 25 | 'main/legacy.js', 26 | 'main/onUncaughtException.js', 27 | 'main/promise.js', 28 | 'main/setTimeout.js', 29 | 'main/stacktrace.js', 30 | 'main/TapReporter.js', 31 | 'main/test.js', 32 | 'main/utilities.js' 33 | ); 34 | 35 | QUnit.on('runEnd', function (data) { 36 | postMessage(data); 37 | }); 38 | 39 | QUnit.start(); 40 | -------------------------------------------------------------------------------- /test/webWorker.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | webWorker 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /test/webWorker.js: -------------------------------------------------------------------------------- 1 | /* eslint-env browser */ 2 | QUnit.module('Web Worker'); 3 | 4 | QUnit.test('main tests', function (assert) { 5 | assert.timeout(10000); 6 | var done = assert.async(); 7 | // eslint-disable-next-line compat/compat -- Test skipped in IE9 8 | var worker = new Worker('webWorker-worker.js'); 9 | 10 | worker.onmessage = function (event) { 11 | assert.equal(event.data.status, 'passed', 'runEnd.status'); 12 | done(); 13 | }; 14 | }); 15 | --------------------------------------------------------------------------------