docs: add way more contributing docs (#846)

[skip ci]
This commit is contained in:
Nolan Lawson 2018-12-19 00:57:48 -08:00 committed by GitHub
parent 32981ffeb2
commit d5eac4e119
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,19 +1,6 @@
# Contributing to Pinafore # Contributing to Pinafore
## Caveats ## Dev server
Please note that this project is _very_ beta right now, and I'm
not in a good position to accept large PRs for
big new features.
I'm making my code open-source for the sake of
transparency and because it's the right thing to do, but I'm hesitant
to start nurturing a community because of
[all that entails](https://nolanlawson.com/2017/03/05/what-it-feels-like-to-be-an-open-source-maintainer/).
So I may not be very responsive to PRs or issues. Thanks for understanding.
## Development
To run a dev server with hot reloading: To run a dev server with hot reloading:
@ -37,9 +24,17 @@ Automatically fix most linting issues:
npm run lint-fix npm run lint-fix
## Testing ## Integration tests
Testing requires running Mastodon itself, meaning the [Mastodon development guide](https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Development-guide.md) is relevant here. In particular, you'll need a recent version of Ruby, Redis, and Postgres running. Integration tests use [TestCafé](https://devexpress.github.io/testcafe/) and a live local Mastodon instance
running on `localhost:3000`.
### Running integration tests
The integration tests require running Mastodon itself,
meaning the[Mastodon development guide](https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Development-guide.md)
is relevant here. In particular, you'll need a recent
version of Ruby, Redis, and Postgres running. For a full list of deps, see `bin/setup-mastodon-in-travis.sh`.
Run integration tests, using headless Chrome by default: Run integration tests, using headless Chrome by default:
@ -54,7 +49,7 @@ Run tests for a particular browser:
BROWSER=safari npm run test-browser BROWSER=safari npm run test-browser
BROWSER=edge npm run test-browser BROWSER=edge npm run test-browser
## Testing in development mode ### Testing in development mode
In separate terminals: In separate terminals:
@ -68,33 +63,46 @@ In separate terminals:
3\. Run a debuggable TestCafé instance: 3\. Run a debuggable TestCafé instance:
npx testcafe --hostname localhost --skip-js-errors --debug-mode firefox tests/spec npx testcafe --hostname localhost --skip-js-errors --debug-mode chrome tests/spec
If you want to export the current data in the Mastodon instance as canned data, ### Test conventions
so that it can be loaded later, run:
npm run backup-mastodon-data The tests have a naming convention:
## Writing tests * `0xx-test-name.js`: tests that don't modify the Mastodon database (read-only)
* `1xx-test-name.js`: tests that do modify the Mastodon database (read-write)
Tests use [TestCafé](https://devexpress.github.io/testcafe/). The tests have a naming convention:
* `0xx-test-name.js`: tests that don't modify the Mastodon database (post, delete, follow, etc.)
* `1xx-test-name.js`: tests that do modify the Mastodon database
In principle the `0-` tests don't have to worry about In principle the `0-` tests don't have to worry about
clobbering each other, whereas the `1-` ones do. clobbering each other, whereas the `1-` ones do.
## Debugging Webpack ### Mastodon used for testing
The Webpack Bundle Analyzer `report.html` and `stats.json` are available publicly via e.g.: There are two parts to the Mastodon data used for testing:
- [dev.pinafore.social/report.html](https://dev.pinafore.social/report.html) 1. A Postgres dump and a tgz containing the media files, located in `fixtures`
- [dev.pinafore.social/stats.json](https://dev.pinafore.social/stats.json) 2. A script that populates the Mastodon backend with test data (`restore-mastodon-data.js`).
This is also available locally after `npm run build` at `.sapper/client/report.html`. The reason we don't use a Postgres dump for everything
is that Mastodon will ignore changes made after a certain period of time, and we
don't want our tests to randomly start breaking one day. Running the script ensures that statuses,
favorites, boosts, etc. are all "fresh".
## Updating Mastodon used for testing ### Updating the test data
You probably don't want to do this, as the `0xx` tests are pretty rigidly defined against the test data.
Write a `1xx` test instead and insert what you need on-the-fly.
If you really need to, though, you can either:
1. Add new test data to `mastodon-data.js`
or
1. Comment out `await restoreMastodonData()` in `run-mastodon.js`
2. Make your changes manually to the live Mastodon
3. Run the steps in the next section to back it up to `fixtures/`
### Updating the Mastodon version
1. Run `rm -fr mastodon` to clear out all Mastodon data 1. Run `rm -fr mastodon` to clear out all Mastodon data
1. Comment out `await restoreMastodonData()` in `run-mastodon.js` to avoid actually populating the database with statuses/favorites/etc. 1. Comment out `await restoreMastodonData()` in `run-mastodon.js` to avoid actually populating the database with statuses/favorites/etc.
@ -111,3 +119,62 @@ Check `mastodon.log` if you have any issues.
There are also some unit tests that run in Node using Mocha. You can find them in `tests/unit` and There are also some unit tests that run in Node using Mocha. You can find them in `tests/unit` and
run them using `npm run test-unit`. run them using `npm run test-unit`.
## Debugging Webpack
The Webpack Bundle Analyzer `report.html` and `stats.json` are available publicly via e.g.:
- [dev.pinafore.social/report.html](https://dev.pinafore.social/report.html)
- [dev.pinafore.social/stats.json](https://dev.pinafore.social/stats.json)
This is also available locally after `npm run build` at `.sapper/client/report.html`.
## Codebase overview
Pinafore uses [SvelteJS](https://svelte.technology) and [SapperJS](https://sapper.svelte.technology). Most of it is a fairly typical Svelte/Sapper project, but there
are some quirks, which are described below. This list of quirks is non-exhaustive.
### Prebuild process
The `template.html` is itself templated. The "template template" has some inline scripts, CSS, and SVGs
injected into it during the build process. SCSS is used for global CSS and themed CSS, but inside of the
components themselves, it's just vanilla CSS because I couldn't figure out how to get Svelte to run a SCSS
preprocessor.
### Lots of small files
Highly modular, highly functional, lots of single-function files. Tends to help with tree-shaking and
code-splitting, as well as avoiding circular dependencies.
### Inferno is loaded dynamically
This is a Svelte project, but `emoji-mart` is used for the emoji picker, and it's written in React. So we
lazy-load the React-compatible Inferno library when we load `emoji-mart`.
### Some third-party code is bundled
For various reasons, `a11y-dialog`, `autosize`, and `timeago` are forked and bundled into the source code.
This was either because something needed to be tweaked or fixed, or I was trimming unused code and didn't
see much value in contributing it back, because it was too Pinafore-specific.
### Every Sapper page is "duplicated"
To get a nice animation on the nav bar when you switch columns, every page is lazy-loaded as `LazyPage.html`.
This "lazy page" is merely delayed a few frames to let the animation run. Therefore there is a duplication
between `src/routes` and `src/routes_pages`. The "lazy page" is in the former, and the actual page is in the
latter. One imports the other.
### There are multiple stores
Originally I conceived of separating out the virtual list into a separate npm package, so I gave it its
own Svelte store (`virtualListStore.js`). This never happened, but it still has its own store. This is useful
anyway, because each store has its state maintained in an LRU cache that allows us to keep the scroll position
in the virtual list e.g. when the user hits the back button.
Also, the main `store.js` store is explicitly
loaded by every component that uses it. So there's no `store` inheritance; every component just declares
whatever store it uses. The main `store.js` is the primary one.
### There is a global event bus
It's in `eventBus.js`. This is useful for some stuff that is hard to do with standard Svelte or DOM events.