feat(gql): implemented resolvers & tests for stream commits & branch commits

This commit is contained in:
Dimitrie Stefanescu
2020-07-22 10:58:08 +01:00
parent 0fe6a0f4af
commit b14dae6829
6 changed files with 152 additions and 41 deletions
+2 -5
View File
@@ -10,7 +10,8 @@ const {
updateCommit,
deleteCommit,
getCommitsByBranchId,
getCommitsByBranchName
getCommitsByBranchName,
getCommitsTotalCountByBranchId
} = require( '../../services/commits' )
const {
@@ -42,10 +43,6 @@ module.exports = {
async author( parent, args, context, info ) {
return await getUserById( { userId: parent.authorId } )
},
async commits( parent, args, context, info ) {
throw new ApolloError( 'not implemented' )
}
},
+14 -5
View File
@@ -13,7 +13,10 @@ const {
getCommitsByBranchId,
getCommitsByBranchName,
getCommitsByUserId,
getCommitsTotalCountByUserId
getCommitsByStreamId,
getCommitsTotalCountByStreamId,
getCommitsTotalCountByUserId,
getCommitsTotalCountByBranchId
} = require( '../../services/commits' )
const {
@@ -28,6 +31,13 @@ module.exports = {
Query: {},
Stream: {
async commits( parent, args, context, info ) {
let { commits: items, cursor } = await getCommitsByStreamId( { streamId: parent.id, limit: args.limit, cursor: args.cursor } )
let totalCount = await getCommitsTotalCountByStreamId( { streamId: parent.id } )
return { items, cursor, totalCount }
},
async commit( parent, args, context, info ) {
throw new ApolloError( 'not implemented' )
}
@@ -46,13 +56,12 @@ module.exports = {
},
Branch: {
async commits( parent, args, context, info ) {
let { commits, cursor } = await getCommitsByBranchId( { branchId: parent.id, limit: args.limit, cursor: args.cursor } )
let totalCount = await getCommitsTotalCountByBranchId( { branchId: parent.id } )
throw new ApolloError( 'not implemented' )
return { items: commits, totalCount, cursor }
}
},
Mutation: {
@@ -22,12 +22,13 @@ type Commit {
referencedObject: String!
realObject: Object
message: String
author: String
authorName: String
authorId: String
createdAt: String
}
type CommitCollectionUserNode {
commitId: String!
id: String!
referencedObject: String!
realObject: Object
message: String
+15 -15
View File
@@ -17,7 +17,7 @@ exports.up = async knex => {
table.boolean( 'completed' ).defaultTo( false )
} )
// Users.
// Users.
await knex.schema.createTable( 'users', table => {
table.string( 'id', 10 ).primary( )
table.string( 'username', 20 ).unique( ).notNullable( )
@@ -34,8 +34,8 @@ exports.up = async knex => {
// Roles.
// Roles keep track of their name and the target resource they are applied to.
// The target resource must be a table name.
// The heigher the weight, the bigger the permissions.
// The target resource must be a table name.
// The heigher the weight, the bigger the permissions.
await knex.schema.createTable( 'user_roles', table => {
table.string( 'name' ).primary( )
table.text( 'description' ).notNullable( )
@@ -44,7 +44,7 @@ exports.up = async knex => {
table.integer( 'weight' ).defaultTo( 100 ).notNullable( )
} )
// Server-wide access control list.
// Server-wide access control list.
await knex.schema.createTable( 'server_acl', table => {
table.string( 'userId', 10 ).references( 'id' ).inTable( 'users' ).primary( ).onDelete( 'cascade' )
table.string( 'role' ).references( 'name' ).inTable( 'user_roles' ).notNullable( ).onDelete( 'cascade' )
@@ -70,13 +70,13 @@ exports.up = async knex => {
} )
// Registered application scopes table.
// Scopes limit what a token can actually do.
// Scopes limit what a token can actually do.
await knex.schema.createTable( 'scopes', table => {
table.string( 'name' ).primary( )
table.text( 'description' ).notNullable( )
} )
// Token >- -< Scopes junction table.
// Token >- -< Scopes junction table.
await knex.schema.createTable( 'token_scopes', table => {
table.string( 'tokenId' ).references( 'id' ).inTable( 'api_tokens' ).notNullable( ).onDelete( 'cascade' ).index( )
table.string( 'scopeName' ).references( 'name' ).inTable( 'scopes' ).notNullable( ).onDelete( 'cascade' ).index( )
@@ -104,7 +104,7 @@ exports.up = async knex => {
table.unique( [ 'userId', 'resourceId' ] )
} )
// Objects Table.
// Objects Table.
// id - the object's *hash*
// totalChildrenCount - how many subchildren, regardless of depth, this object has
// totalChildrenCountByDepth - how many subchildren does this object have at a specific nesting depth.
@@ -119,11 +119,11 @@ exports.up = async knex => {
table.jsonb( 'data' )
} )
// Closure table for tracking the nesting relationships of objects.
// Closure table for tracking the nesting relationships of objects.
// Note: the usecase optimised for is that when we request an object, we either:
// a) interactively request/query for its subchildren (sequentially)
// or
// b) we want all of it!
// b) we want all of it!
await knex.schema.createTable( 'object_children_closure', table => {
table.string( 'parent' ).notNullable( ).index( )
table.string( 'child' ).notNullable( ).index( )
@@ -132,8 +132,8 @@ exports.up = async knex => {
table.index( [ 'parent', 'minDepth' ], 'full_pcd_index' )
} )
// Commit table.
// Any object can be "blessed" as a commit.
// Commit table.
// Any object can be "blessed" as a commit.
await knex.schema.createTable( 'commits', table => {
table.string( 'id', 10 ).primary( )
table.string( 'referencedObject' ).references( 'id' ).inTable( 'objects' ).notNullable( )
@@ -142,7 +142,7 @@ exports.up = async knex => {
table.timestamp( 'createdAt' ).defaultTo( knex.fn.now( ) )
} )
// Commit inheritance table.
// Commit inheritance table.
// Tracks the inheritance of commits. A commit may have:
// - one ancestor (simple sequential push)
// - more ancestors (result of a merge)
@@ -152,7 +152,7 @@ exports.up = async knex => {
table.unique( [ 'parent', 'child' ], 'commit_parent_child_index' )
} )
// Branches table.
// Branches table.
// A branch is a end-user scope-bound collection of commits.
await knex.schema.createTable( 'branches', table => {
table.string( 'id', 10 ).primary( )
@@ -165,7 +165,7 @@ exports.up = async knex => {
table.unique( [ 'streamId', 'name' ] )
} )
// Junction Table Branches >- -< Commits
// Junction Table Branches >- -< Commits
await knex.schema.createTable( 'branch_commits', table => {
table.string( 'branchId', 10 ).references( 'id' ).inTable( 'branches' ).notNullable( ).onDelete( 'cascade' )
table.string( 'commitId' ).references( 'id' ).inTable( 'commits' ).notNullable( ).onDelete( 'cascade' )
@@ -206,4 +206,4 @@ exports.down = async knex => {
await knex.raw( `DROP TYPE IF EXISTS speckle_reference_type ` )
await knex.raw( `DROP TYPE IF EXISTS speckle_acl_role_type ` )
}
}
+3 -3
View File
@@ -85,7 +85,7 @@ module.exports = {
async getCommitsByBranchId( { branchId, limit, cursor } ) {
limit = limit || 20
let query = BranchCommits( ).columns( [ 'commitId', 'message', 'referencedObject', { author: 'name' }, { authorId: 'users.id' }, 'commits.createdAt' ] ).select( )
let query = BranchCommits( ).columns( [ { id: 'commitId' }, 'message', 'referencedObject', { authorName: 'name' }, { authorId: 'users.id' }, 'commits.createdAt' ] ).select( )
.join( 'commits', 'commits.id', 'branch_commits.commitId' )
.join( 'users', 'commits.author', 'users.id' )
.where( 'branchId', branchId )
@@ -126,7 +126,7 @@ module.exports = {
async getCommitsByStreamId( { streamId, limit, cursor } ) {
limit = limit || 20
let query = StreamCommits( )
.columns( [ 'commitId', 'message', 'referencedObject', { author: 'name' }, { authorId: 'users.id' }, 'commits.createdAt' ] ).select( )
.columns( [ { id: 'commitId' }, 'message', 'referencedObject', { authorName: 'name' }, { authorId: 'users.id' }, 'commits.createdAt' ] ).select( )
.join( 'commits', 'commits.id', 'stream_commits.commitId' )
.join( 'users', 'commits.author', 'users.id' )
.where( 'streamId', streamId )
@@ -147,7 +147,7 @@ module.exports = {
let query =
Commits( )
.columns( [ 'commitId', 'message', 'referencedObject', 'commits.createdAt', { streamId: 'stream_commits.streamId' }, { streamName: 'streams.name' } ] ).select( )
.columns( [ { id: 'commitId' }, 'message', 'referencedObject', 'commits.createdAt', { streamId: 'stream_commits.streamId' }, { streamName: 'streams.name' } ] ).select( )
.join( 'stream_commits', 'commits.id', 'stream_commits.commitId' )
.join( 'streams', 'stream_commits.streamId', 'streams.id' )
.where( 'author', userId )
+115 -11
View File
@@ -453,7 +453,7 @@ describe( 'GraphQL API Core', ( ) => {
for ( let i = 10; i < 20; i++ ) {
let c1 = {
message: 'what a message for a first commit',
message: `what a message for commit number ${i}`,
streamId: ts1,
objectId: objIds[ i ],
branchName: 'master',
@@ -461,14 +461,15 @@ describe( 'GraphQL API Core', ( ) => {
let res = await sendRequest( userA.token, { query: `mutation( $myCommit: CommitCreateInput! ) { commitCreate( commit: $myCommit ) }`, variables: { myCommit: c1 } } )
}
const res = await sendRequest( userA.token, { query: `{ user { commits( limit: 3 ) { totalCount cursor items { commitId message referencedObject } } } }` } )
const res = await sendRequest( userA.token, { query: `{ user { commits( limit: 3 ) { totalCount cursor items { id message referencedObject } } } }` } )
expect( res ).to.be.json
expect( res.body.errors ).to.not.exist
expect( res.body.data.user.commits.totalCount ).to.equal( 11 )
expect( res.body.data.user.commits.cursor ).to.exist
expect( res.body.data.user.commits.items.length ).to.equal( 3 )
const res2 = await sendRequest( userA.token, { query: `{ user { commits( limit: 3, cursor: "${res.body.data.user.commits.cursor}") { totalCount cursor items { commitId message referencedObject } } } }` } )
const res2 = await sendRequest( userA.token, { query: `{ user { commits( limit: 3, cursor: "${res.body.data.user.commits.cursor}") { totalCount cursor items { id message referencedObject } } } }` } )
expect( res2 ).to.be.json
expect( res2.body.errors ).to.not.exist
expect( res2.body.data.user.commits.totalCount ).to.equal( 11 )
@@ -545,6 +546,7 @@ describe( 'GraphQL API Core', ( ) => {
expect( stream.collaborators[ 1 ].role ).to.equal( 'stream:owner' )
} )
let bees = [ ]
it( 'should retrieve all stream branches', async ( ) => {
let query = `
query{
@@ -573,6 +575,8 @@ describe( 'GraphQL API Core', ( ) => {
expect( res.body.data.stream.branches.totalCount ).to.equal( 3 )
expect( res.body.data.stream.branches.cursor ).to.exist
bees = res.body.data.stream.branches.items
let query2 = `
query{
stream(id: "${ts1}"){
@@ -600,23 +604,123 @@ describe( 'GraphQL API Core', ( ) => {
} )
it( 'should retrieve a stream branch', async ( ) => {
// note: adding another commit for the sake of it
const res1 = await sendRequest( userA.token, { query: `mutation($branch:BranchUpdateInput!) { branchUpdate(streamId:"${ts1}", branch:$branch) }`, variables: { branch: { id: b1.id, commits: [ c2.id ] } } } )
const res = await sendRequest( userA.token, { query: `query { stream(id:"${ts1}") { branch(id:"${retrievedStream.branches.branches[0].id}") { name description commits { totalCount } } } } ` } )
const res = await sendRequest( userA.token, { query: `query { stream(id:"${ts1}") { branch( name: "${bees[1].name}" ) { name description } } } ` } )
expect( res ).to.be.json
expect( res.body.errors ).to.not.exist
expect( res.body.data.stream.branch.name ).to.equal( 'branch 1' )
expect( res.body.data.stream.branch.commits.totalCount ).to.equal( 2 )
expect( res.body.data.stream.branch.name ).to.equal( 'dim/dev' )
} )
it( 'should retrieve a branch`s commits', async ( ) => {
assert.fail( 'todo' )
let query = `
query {
stream( id: "${ts1}" ) {
branch( name: "master" ) {
id
name
commits( limit: 5 ) {
totalCount
cursor
items {
id
message
createdAt
referencedObject
authorId
}
}
}
}
}
`
const res = await sendRequest( userA.token, { query: query } )
expect( res.body.data.stream.branch.commits.items.length ).to.equal( 5 )
expect( res.body.data.stream.branch.commits.items[ 0 ] ).to.have.property( 'id' )
expect( res.body.data.stream.branch.commits.items[ 0 ] ).to.have.property( 'message' )
expect( res.body.data.stream.branch.commits.items[ 0 ] ).to.have.property( 'createdAt' )
let query2 = `
query {
stream( id: "${ts1}" ) {
branch( name: "master" ) {
id
name
commits( limit: 3, cursor: "${res.body.data.stream.branch.commits.cursor}" ) {
totalCount
cursor
items {
id
message
createdAt
referencedObject
authorId
authorName
}
}
}
}
}`
const res2 = await sendRequest( userA.token, { query: query2 } )
// console.log( res2.body.errors )
// console.log( res2.body.data.stream.branch.commits )
expect( res2.body.data.stream.branch.commits.items.length ).to.equal( 3 )
expect( res2.body.data.stream.branch.commits.items[ 0 ] ).to.have.property( 'id' )
expect( res2.body.data.stream.branch.commits.items[ 0 ] ).to.have.property( 'message' )
expect( res2.body.data.stream.branch.commits.items[ 0 ] ).to.have.property( 'createdAt' )
} )
it( 'should retrieve all stream commits', async ( ) => {
assert.fail( 'todo' )
let query = `
query {
stream( id: "${ts1}" ) {
commits( limit: 10 ) {
totalCount
cursor
items {
id
message
authorId
authorName
}
}
}
}
`
const res = await sendRequest( userA.token, { query: query } )
expect( res ).to.be.json
expect( res.body.errors ).to.not.exist
expect( res.body.data.stream.commits.items.length ).to.equal( 10 )
expect( res.body.data.stream.commits.totalCount ).to.equal( 12 )
let query2 = `
query {
stream( id: "${ts1}" ) {
commits( limit: 10, cursor: "${res.body.data.stream.commits.cursor}" ) {
totalCount
cursor
items {
id
message
authorId
authorName
}
}
}
}
`
const res2 = await sendRequest( userA.token, { query: query2 } )
console.log( res2.body.errors )
console.log( res2.body.data.stream.commits )
expect( res2 ).to.be.json
expect( res2.body.errors ).to.not.exist
expect( res2.body.data.stream.commits.items.length ).to.equal( 2 )
} )
it( 'should retrieve a stream commit', async ( ) => {