test: wip e2e
This commit is contained in:
@@ -4,5 +4,6 @@
|
||||
"javascriptreact",
|
||||
"vue",
|
||||
"graphql"
|
||||
]
|
||||
],
|
||||
"eslint.enable": true
|
||||
}
|
||||
@@ -1,2 +1 @@
|
||||
|
||||
schema.graphql
|
||||
|
||||
@@ -16,7 +16,8 @@ module.exports = {
|
||||
{
|
||||
env: 'literal'
|
||||
}
|
||||
]
|
||||
],
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
},
|
||||
|
||||
parserOptions: {
|
||||
@@ -26,4 +27,4 @@ module.exports = {
|
||||
plugins: [
|
||||
'graphql'
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/app'
|
||||
]
|
||||
'@vue/app',
|
||||
],
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"graphql-type-json": "^0.2.1",
|
||||
"shortid": "^2.2.8",
|
||||
"vue": "^2.5.16",
|
||||
"vue-apollo": "^3.0.0-beta.10",
|
||||
"vue-router": "^3.0.1",
|
||||
|
||||
+13
-4
@@ -1,13 +1,22 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<div id="nav">
|
||||
<router-link to="/">Home</router-link> |
|
||||
<router-link to="/about">About</router-link>
|
||||
<ChannelList/>
|
||||
<div class="content">
|
||||
<router-view/>
|
||||
</div>
|
||||
<router-view/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ChannelList from '@/components/ChannelList.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ChannelList,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
#app
|
||||
font-family 'Avenir', Helvetica, Arial, sans-serif
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.7 KiB |
@@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<ApolloQuery :query="require('../graphql/channels.gql')">
|
||||
<template slot-scope="{ result: { data, loading } }">
|
||||
<div v-if="loading">Loading...</div>
|
||||
<div v-else-if="data" class="channels">
|
||||
<router-link
|
||||
v-for="channel of data.channels"
|
||||
:key="channel.id"
|
||||
:to="{ name: 'channel', params: { id: channel.id } }"
|
||||
class="channel"
|
||||
>
|
||||
<div class="name">{{ channel.name }}</div>
|
||||
<div class="id">{{ channel.id }}</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
</ApolloQuery>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.channel
|
||||
display block
|
||||
|
||||
.id
|
||||
font-family monospace
|
||||
font-size 10px
|
||||
</style>
|
||||
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<div class="channel-view">
|
||||
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,36 +0,0 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<ApolloQuery :query="require('../graphql/hello.gql')">
|
||||
<template slot-scope="{ result: { data, loading } }">
|
||||
<div v-if="loading">Loading...</div>
|
||||
<div v-else-if="data">{{ data.hello }}</div>
|
||||
</template>
|
||||
</ApolloQuery>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HelloWorld',
|
||||
props: {
|
||||
msg: String
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="stylus">
|
||||
h3
|
||||
margin 40px 0 0
|
||||
|
||||
ul
|
||||
list-style-type none
|
||||
padding 0
|
||||
|
||||
li
|
||||
display inline-block
|
||||
margin 0 10px
|
||||
|
||||
a
|
||||
color #42b983
|
||||
</style>
|
||||
@@ -0,0 +1,6 @@
|
||||
<template>
|
||||
<div class="welcome-view">
|
||||
<h1>Welcome!</h1>
|
||||
<p>Select a channel to start messaging</p>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,13 @@
|
||||
const channels = [
|
||||
{ id: 'general', name: 'General' },
|
||||
{ id: 'random', name: 'Random' },
|
||||
{ id: 'help', name: 'Help' },
|
||||
]
|
||||
|
||||
exports.getAll = (context) => {
|
||||
return channels
|
||||
}
|
||||
|
||||
exports.getOne = (id, context) => {
|
||||
return channels.find(c => c.id === id)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
const shortid = require('shortid')
|
||||
const triggers = require('../triggers')
|
||||
|
||||
const messages = []
|
||||
|
||||
exports.getAll = (channelId, context) => {
|
||||
return messages.filter(m => m.channelId === channelId)
|
||||
}
|
||||
|
||||
exports.add = ({ channelId, content }, context) => {
|
||||
const message = {
|
||||
id: shortid(),
|
||||
userId: context.userId,
|
||||
channelId: channelId,
|
||||
content: content,
|
||||
dateAdded: Date.now(),
|
||||
}
|
||||
messages.push(message)
|
||||
context.pubsub.publish(triggers.MESSAGE_CHANGED, {
|
||||
messageChanged: {
|
||||
type: 'added',
|
||||
message,
|
||||
},
|
||||
})
|
||||
return message
|
||||
}
|
||||
@@ -1,26 +1,26 @@
|
||||
const GraphQLJSON = require('graphql-type-json')
|
||||
const { withFilter } = require('graphql-subscriptions')
|
||||
// Subs
|
||||
const triggers = require('./triggers')
|
||||
// Connectors
|
||||
const channels = require('./connectors/channels')
|
||||
|
||||
module.exports = {
|
||||
JSON: GraphQLJSON,
|
||||
|
||||
Query: {
|
||||
hello: (root, { name }) => `Hello ${name || 'World'}!`
|
||||
|
||||
channels: (root, args, context) => channels.getAll(context),
|
||||
channel: (root, { id }, context) => channels.getOne(id, context),
|
||||
},
|
||||
|
||||
Mutation: {
|
||||
myMutation: (root, args, context) => {
|
||||
const message = 'My mutation completed!'
|
||||
context.pubsub.publish('hey', { mySub: message })
|
||||
return message
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
Subscription: {
|
||||
mySub: {
|
||||
subscribe: (parent, args, { pubsub }) => pubsub.asyncIterator('hey')
|
||||
}
|
||||
|
||||
}
|
||||
messageChanged: withFilter(
|
||||
(parent, args, { pubsub }) => pubsub.asyncIterator(triggers.MESSAGE_CHANGED),
|
||||
(payload, vars) => payload.messageChanged.channelId === vars.channelId
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,21 +1,63 @@
|
||||
scalar JSON
|
||||
|
||||
type User {
|
||||
id: ID!
|
||||
nickname: String!
|
||||
email: String
|
||||
}
|
||||
|
||||
# Channel of messages
|
||||
type Channel {
|
||||
id: ID!
|
||||
name: String!
|
||||
messages: [Message]
|
||||
}
|
||||
|
||||
# User messages
|
||||
type Message {
|
||||
id: ID!
|
||||
content: String!
|
||||
# Author of the message
|
||||
user: User
|
||||
dateAdded: JSON
|
||||
dateUpdated: JSON
|
||||
}
|
||||
|
||||
input MessageAdd {
|
||||
channelId: ID!
|
||||
content: String!
|
||||
}
|
||||
|
||||
input MessageUpdate {
|
||||
id: ID!
|
||||
content: String!
|
||||
}
|
||||
|
||||
type MessageChanged {
|
||||
type: MessageChangedType!
|
||||
message: Message!
|
||||
}
|
||||
|
||||
enum MessageChangedType {
|
||||
added
|
||||
updated
|
||||
removed
|
||||
}
|
||||
|
||||
type Query {
|
||||
# Test query with a parameter
|
||||
hello(name: String): String!
|
||||
|
||||
userCurrent: User
|
||||
channels: [Channel]
|
||||
channel (id: ID!): Channel
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
myMutation: String!
|
||||
|
||||
userLogin (email: String!, password: String!): User
|
||||
userLogout: Boolean
|
||||
messageAdd (input: MessageAdd!): Message!
|
||||
messageUpdate (input: MessageUpdate!): Message!
|
||||
messageRemove (id: ID!): Message!
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
mySub: String!
|
||||
|
||||
messageChanged (channelId: ID!): MessageChanged!
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
MESSAGE_CHANGED: 'message_changed',
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#import "./channelFragment.gql"
|
||||
#import "./messageFragment.gql"
|
||||
|
||||
query channel ($id: ID!) {
|
||||
channel (id: $id) {
|
||||
...channel
|
||||
messages {
|
||||
...message
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
fragment channel on Channel {
|
||||
id
|
||||
name
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#import "./channelFragment.gql"
|
||||
|
||||
query channels {
|
||||
channels {
|
||||
...channel
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
query hello {
|
||||
hello
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#import "./messageFragment.gql"
|
||||
|
||||
mutation messageAdd ($input: MessageAdd!) {
|
||||
messageAdd (input: $input) {
|
||||
...message
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#import "./messageFragment.gql"
|
||||
|
||||
subscription messageChanged ($channelId: ID!) {
|
||||
messageChanged (channelId: $channelId) {
|
||||
type
|
||||
message {
|
||||
...message
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#import "./userFragment.gql"
|
||||
|
||||
fragment message on Message {
|
||||
id
|
||||
content
|
||||
user {
|
||||
...user
|
||||
}
|
||||
dateAdded
|
||||
dateUpdated
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#import "./messageFragment.gql"
|
||||
|
||||
mutation messageRemove ($id: ID!) {
|
||||
messageRemove (id: $id) {
|
||||
...message
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#import "./messageFragment.gql"
|
||||
|
||||
mutation messageUpdate ($input: MessageUpdate!) {
|
||||
messageUpdate (input: $input) {
|
||||
...message
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
fragment user on User {
|
||||
id
|
||||
nickname
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#import "./userFragment.gql"
|
||||
|
||||
mutation userLogin ($email: String!, $password: String!) {
|
||||
userLogin (email: $email, password: $password) {
|
||||
...user
|
||||
email
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
mutation userLogout {
|
||||
userLogout
|
||||
}
|
||||
@@ -10,5 +10,5 @@ new Vue({
|
||||
router,
|
||||
store,
|
||||
provide: createProvider().provide(),
|
||||
render: h => h(App)
|
||||
render: h => h(App),
|
||||
}).$mount('#app')
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import Home from './views/Home.vue'
|
||||
import About from './views/About.vue'
|
||||
import WelcomeView from './components/WelcomeView.vue'
|
||||
import ChannelView from './components/ChannelView.vue'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
export default new Router({
|
||||
mode: 'history',
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
component: Home
|
||||
component: WelcomeView,
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
name: 'about',
|
||||
component: About
|
||||
}
|
||||
]
|
||||
path: '/:id',
|
||||
name: 'channel',
|
||||
component: ChannelView,
|
||||
props: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
@@ -12,5 +12,5 @@ export default new Vuex.Store({
|
||||
},
|
||||
actions: {
|
||||
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<template>
|
||||
<div class="about">
|
||||
<h1>This is an about page</h1>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,18 +0,0 @@
|
||||
<template>
|
||||
<div class="home">
|
||||
<img src="../assets/logo.png">
|
||||
<HelloWorld msg="Welcome to Your Vue.js App"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// @ is an alias to /src
|
||||
import HelloWorld from '@/components/HelloWorld.vue'
|
||||
|
||||
export default {
|
||||
name: 'home',
|
||||
components: {
|
||||
HelloWorld
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -23,7 +23,7 @@ const defaultOptions = {
|
||||
// You need to pass a `wsEndpoint` for this to work
|
||||
websocketsOnly: false,
|
||||
// Is being rendered on the server?
|
||||
ssr: false
|
||||
ssr: false,
|
||||
// Override default http link
|
||||
// link: myLink,
|
||||
// Override default cache
|
||||
@@ -37,13 +37,18 @@ export function createProvider (options = {}) {
|
||||
// Create apollo client
|
||||
const { apolloClient, wsClient } = createApolloClient({
|
||||
...defaultOptions,
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
apolloClient.wsClient = wsClient
|
||||
|
||||
// Create vue apollo provider
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: apolloClient
|
||||
defaultClient: apolloClient,
|
||||
defaultOptions: {
|
||||
$query: {
|
||||
fetchPolicy: 'cache-and-network',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return apolloProvider
|
||||
|
||||
@@ -6,6 +6,6 @@ module.exports = (on, config) => {
|
||||
integrationFolder: 'tests/e2e/specs',
|
||||
screenshotsFolder: 'tests/e2e/screenshots',
|
||||
videosFolder: 'tests/e2e/videos',
|
||||
supportFile: 'tests/e2e/support/index.js'
|
||||
supportFile: 'tests/e2e/support/index.js',
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module.exports = {
|
||||
pluginOptions: {
|
||||
graphqlMock: true,
|
||||
apolloEngine: false
|
||||
}
|
||||
apolloEngine: false,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -6935,6 +6935,10 @@ shell-quote@^1.6.1:
|
||||
array-reduce "~0.0.0"
|
||||
jsonify "~0.0.0"
|
||||
|
||||
shortid@^2.2.8:
|
||||
version "2.2.8"
|
||||
resolved "https://registry.yarnpkg.com/shortid/-/shortid-2.2.8.tgz#033b117d6a2e975804f6f0969dbe7d3d0b355131"
|
||||
|
||||
signal-exit@^3.0.0, signal-exit@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
|
||||
|
||||
Reference in New Issue
Block a user