diff --git a/Source/dom/models/Library.js b/Source/dom/models/Library.js index e4cd0703..b734b804 100644 --- a/Source/dom/models/Library.js +++ b/Source/dom/models/Library.js @@ -174,25 +174,12 @@ export class Library extends WrappedObject { const collector = MSForeignObjectCollector.alloc().initWithProvider( provider ) - const shareableObjectRefsMap = collector.buildCollectionWithFilter(null) - - const currentId = this.id - const currentName = this.name - - const shareableObjectRefsForCurrentLib = toArray( - shareableObjectRefsMap - ).find( - (o) => - o.library && - String(o.library.libraryID()) === currentId && - String(o.library.name()) === currentName + const shareableObjectRefs = toArray( + collector.collectImportableReferencesFromLibrary(this.sketchObject) ) - if (!shareableObjectRefsForCurrentLib) { - return [] - } const documentData = document._getMSDocumentData() - return toArray(shareableObjectRefsForCurrentLib.objectRefs).map((ref) => { + return toArray(shareableObjectRefs).map((ref) => { const obj = ImportableObject.fromNative(ref) obj._documentData = documentData return obj diff --git a/Source/dom/models/__tests__/Library.test.js b/Source/dom/models/__tests__/Library.test.js index 235f8799..04062966 100644 --- a/Source/dom/models/__tests__/Library.test.js +++ b/Source/dom/models/__tests__/Library.test.js @@ -42,9 +42,13 @@ function createLibrary(testOutputPath = outputPath()) { } test('should create a library from a document', () => { - createLibrary().then((lib) => { - expect(lib.type).toBe('Library') - expect(getLibraries().find((d) => d.id === lib.id)).toEqual(lib) + return createLibrary().then((lib) => { + try { + expect(lib.type).toBe('Library') + expect(getLibraries().find((d) => d.id === lib.id)).toEqual(lib) + } finally { + lib.remove() + } }) }) @@ -55,49 +59,94 @@ test('should list the libraries', () => { expect(libraries[0].type).toBe('Library') }) -test('should be able to get the list of symbols to be imported', (_context, document) => { - createLibrary().then((lib) => { - expect(lib.getImportableSymbolReferencesForDocument(document)[0].type).toBe( - 'ImportableObject' - ) +test('should be able to get the list of symbols to be imported', () => { + return createLibrary().then((lib) => { + try { + // Library.getImportableSymbolReferencesForDocument() and its sibling methods all expect + // an actual Document as an argument, not a DocumentData we get from the test environment + const document = new Document() + const importableSymbols = lib.getImportableSymbolReferencesForDocument( + document + ) + expect(importableSymbols[0].type).toBe('ImportableObject') + expect(importableSymbols[0].name).toBe('Test') + expect(importableSymbols[0].objectType).toBe( + Library.ImportableObjectType.Symbol + ) + } finally { + lib.remove() + } + }) +}) + +test('should return references to already imported local copies of symbols if they exist', () => { + return createLibrary().then((lib) => { + try { + const document = new Document() + const refBeforeImport = lib.getImportableSymbolReferencesForDocument( + document + )[0] + expect(refBeforeImport.sketchObject.remoteReference()).toBeNull() + + refBeforeImport.import() + + const refAfterImport = lib.getImportableSymbolReferencesForDocument( + document + )[0] + expect(refAfterImport.sketchObject.remoteReference()).not.toBeNull() + } finally { + lib.remove() + } }) }) test('should disable a library', () => { - createLibrary().then((lib) => { - expect(lib.enabled).toBe(true) - lib.enabled = false - expect(lib.enabled).toBe(false) - lib.enabled = true - expect(lib.enabled).toBe(true) + return createLibrary().then((lib) => { + try { + expect(lib.enabled).toBe(true) + lib.enabled = false + expect(lib.enabled).toBe(false) + lib.enabled = true + expect(lib.enabled).toBe(true) + } finally { + lib.remove() + } }) }) test('should get the lastModifiedAt date', () => { - createLibrary().then((lib) => { - expect(lib.lastModifiedAt instanceof Date).toBe(true) + return createLibrary().then((lib) => { + try { + expect(lib.lastModifiedAt instanceof Date).toBe(true) + } finally { + lib.remove() + } }) }) test('should get the document of the library', () => { const testOutputPath = outputPath() - - createLibrary(testOutputPath).then((lib) => { - const libDocument = lib.getDocument() - - expect(libDocument.type).toBe('Document') - expect(libDocument.path).toBe( - String( - NSString.stringWithString( - `${testOutputPath}/sketch-api-unit-tests-library.sketch` + + return createLibrary(testOutputPath).then((lib) => { + try { + const libDocument = lib.getDocument() + + expect(libDocument.type).toBe('Document') + expect(libDocument.path).toBe( + String( + NSString.stringWithString( + `${testOutputPath}/sketch-api-unit-tests-library.sketch` + ) ) ) - ) + } finally { + lib.remove() + } }) }) test('should remove a library', () => { - createLibrary().then((lib) => { + return createLibrary().then((lib) => { lib.remove() expect(getLibraries().find((d) => d.id === lib.id)).toBe(undefined) diff --git a/webpack.tests.config.js b/webpack.tests.config.js index 95615102..0e42c2c7 100644 --- a/webpack.tests.config.js +++ b/webpack.tests.config.js @@ -185,49 +185,48 @@ function source(identifier, tests) { // Runs all test suites const numSuites = Object.entries(suites).length let results = [] + let promise = Promise.resolve() Object.entries(suites).forEach(([suiteTitle, val], index) => { const numTests = Object.entries(val.source.tests).length Object.entries(val.source.tests).forEach(([title, test], testIndex) => { - console.log(`Running test: ${suiteTitle} ${title}`) - - let status = 'pending' - let failureReason - - try { - expect.resetAssertionsLocalState() - - // All tests are given the plugin command context and a new document data - // object. - // - // Note: This is not a full Document instance wrapping MSDocument. Using - // MSDocument slows down tests massively, so we rely on the private API - // creating document data from MSDocumentData. - test(context, createDocumentData()) - status = 'passed' - } catch (err) { - status = 'failed' - failureReason = getTestFailure(err) - } - - const fraction = - index / numSuites + (testIndex + 1) / numTests / numSuites - - results.push({ - ancestorTitles: [suiteTitle], // we don't have nested test suites in the API but sticking to Jest types anyway. - fullName: `${suiteTitle} ${title}`, - status, - title, - relativePath: `.${val.path.split(/SketchAPI/)[1]}`, - failureReason, - }) - - if (!onProgress) return - - onProgress({ fraction, results }) + promise = promise + .then(() => { + console.log(`Running test: ${suiteTitle} ${title}`) + return test(context, createDocumentData()) + }) + .then(() => { + results.push({ + ancestorTitles: [suiteTitle], + fullName: `${suiteTitle} ${title}`, + status: 'passed', + title, + relativePath: `.${val.path.split(/SketchAPI/)[1]}`, + failureReason: undefined, + }) + }) + .catch((err) => { + results.push({ + ancestorTitles: [suiteTitle], + fullName: `${suiteTitle} ${title}`, + status: 'failed', + title, + relativePath: `.${val.path.split(/SketchAPI/)[1]}`, + failureReason: getTestFailure(err), + }) + }) + .then(() => { + if (onProgress) { + const fraction = + index / numSuites + (testIndex + 1) / numTests / numSuites + onProgress({ fraction, results }) + } + }) }) }) + + return promise } return ` @@ -298,7 +297,10 @@ function source(identifier, tests) { console.log(\`🏇 Running \${Object.keys(testSuites).length} test suites…\`) - const result = runner({ + const { createFiber } = require('sketch/async') + const fiber = createFiber(); + + runner({ context, expect, suites: testSuites, @@ -314,19 +316,11 @@ function source(identifier, tests) { }, prepareStackTrace }) - - const data = NSString.alloc().initWithString(JSON.stringify(result, null, 2)) - const err = MOPointer.alloc().init() - - data.writeToFile_atomically_encoding_error( - output, - false, - NSUTF8StringEncoding, - err - ) - - console.log('✅ Test results saved to: ' + output) - sketch.UI.message('✅ Test results saved to disk.') + .finally(() => { + console.log('✅ Test results saved to: ' + output) + sketch.UI.message('✅ Test results saved to disk.') + fiber.cleanup() + }) } ` }